اشتراکها
مشکل این روش این است که بعد از یک بار اعتبار سنجی دفعه بعد با زدن هر کلید داخل تکست باکس میخواد بره به بانک و اطلاعات را چک کنه.
نظرات مطالب
پیاده سازی UnitOfWork به وسیله MEF
پردازش IValidatableObject سمت سرور هست. فقط نمایش نتیجه این نوع اعتبار سنجی سمت سرور، در سمت کلاینت بعد از post back کامل نمایش داده میشه.
مراجعه کنید به قسمت پنجم سری MVVM که در مورد نحوه استفاده از data annotations برای اعتبار سنجی در WPF مطلب داره (محل دریافت دوم کل سری).
بله. اگر از ASP.NET MVC استفاده کنید به صورت خودکار تبدیل به پیغامهای اعتبار سنجی سمت کاربر هم میشود. ولی در کل اثر بررسی سمت سرور هم دارد و همین پیغامها توسط DbEntityValidationException قابل دریافت هستند.
نظرات مطالب
آشنایی با NHibernate - قسمت دهم
لطفا قسمت آخر را مطالعه بفرمائید (استفاده از قیودات تعریف شده و سیستم اعتبار سنجی به صورت یکپارچه با NHibernate). هم FHN است و هم با تزریقی که صورت گرفته یکپارچه شده و هم از ویژگیها استفاده نشده.
نظرات مطالب
آشنایی با NHibernate - قسمت دهم
از پاسخگویی شما ممنونم.
آیا امکان اعتبار سنجی بصورت یکپارچه با FNH در حالتی که از ویژگیها استفاده نمیکنیم وجود دارد؟ (در مثال شما این کار انجام نمیشود)
آیا امکان اعتبار سنجی بصورت یکپارچه با FNH در حالتی که از ویژگیها استفاده نمیکنیم وجود دارد؟ (در مثال شما این کار انجام نمیشود)
پس از برقراری ارتباط بین فرم و مدل آن در قسمت قبل، مرحلهی بعدی طراحی یک فرم خوب، اعتبارسنجی ورودیهای کاربران است و واکنش نشان دادن به ورودیهای نامطلوب.
کلاسهای CSS اعتبارسنجی در Angular
زمانیکه Angular فرمی را تحت نظر قرار میدهد، کلاسهای CSS خاصی را نیز بر اساس حالات عناصر مختلف آن، به آنها متصل خواهد کرد. بر این اساس میتوان ظاهر این المانها را سفارشی سازی نمود. این کلاسها به شرح زیر هستند:
برای اینکه بتوانیم این موارد را در عمل مشاهده کنیم، به ابتدای فرم مثال این سری، تغییرات ذیل را اعمال خواهیم کرد:
برای اینکه مشخص کنیم چه کلاسی به المان firstName متصل شدهاست، ابتدا نیاز است یک template reference variable را برای آن تعریف کنیم که اینکار را توسط معرفی firstName# انجام دادهایم. به این ترتیب است که میتوان به خاصیت className آن در ادامه دسترسی یافت.
تصویر فوق کلاسهایی را نمایش میدهد که در اولین بار نمایش فرم، به المان firstName متصل شدهاند. برای مثال در این حالت کلاس ng-pristine قابل مشاهدهاست و هنوز تغییری در آن حاصل نشدهاست.
در ادامه اگر حرفی را به آن اضافه کنیم:
هنوز هم ng-untouched آن برقرار است؛ اما ng-pristine آن به ng-dirty تبدیل شدهاست. در اینجا حتی اگر کل اطلاعات فیلد را نیز حذف کنیم و آنرا خالی کنیم یا به حالت اول بازگردانیم نیز کلاس ng-dirty قابل مشاهدهاست. بنابراین اگر حالت فیلدی dirty شد، همواره به همین حالت باقی میماند.
در این لحظه اگر با Tab به فیلد دیگری در فرم مراجعه کنیم:
در اینجا است که کلاس ng-untouched به ng-touched تبدیل میشود. بنابراین کلاسهای مختلف لمس یک فیلد، ارتباطی به افزوده شدن یا حذف کاراکتری از یک فیلد ندارند و فقط به از دست رفتن focus و مراجعهی به فیلد دیگری مرتبط میشوند.
اگر به المان تغییر یافتهی فوق دقت کنید، ویژگی required نیز به آن اضافه شدهاست (علاوه بر template reference variable ایی که تعریف کردیم). در این حالت کل فیلد را خالی کنید:
همانطور که مشاهده میکنید، اکنون کلاس ng-valid به کلاس ng-invalid تغییر یافتهاست.
ارتباط بین کلاسهای CSS اعتبارسنجی و خواص ngModel
تمام کلاسهای -ng ایی که در بالا معرفی شدند، معادلهای خواص ngModel ایی نیز دارند. فقط کافی است -ng آنها را حذف کنید، باقیماندهی آن، نام خاصیت متناظری در ngModel خواهد بود. برای مثال کلاس ng-untouched به خاصیت untouched نگاشت میشود و به همین ترتیب برای مابقی.
template reference variable ایی را که تا به اینجا به المان اضافه کردیم (firstName#) به خواص همان المان دسترسی دارد (مانند className آن). اما در ادامه میخواهیم این متغیر به ngModel و خواص آن دسترسی داشته باشد و میدان دید آن تغییر کند. به همین جهت تنها کافی است تا ngModel را به این متغیر انتساب دهیم:
پس از این تغییر اکنون template reference variable تعریف شده میتواند برای نمونه به خاصیت dirty شیء ngModel دسترسی پیدا کند.
یک نکته: در حالت خواص valid و invalid که مرتبط با اعتبارسنجی هستند، خاصیت سومی نیز به نام errors وجود دارد که حاوی اطلاعات بیشتری در مورد خطای اعتبارسنجی رخ دادهاست. بنابراین وجود این خاصیت و نال نبودن آن نیز دلالت بر وجود یک خطای اعتبارسنجی است. از خاصیت errors در ادامهی بحث در قسمت «مدیریت چندین خطای همزمان اعتبارسنجی» استفاده خواهیم کرد.
نمایش بهتر خطاهای اعتبارسنجی با بررسی خواص ngModel
یکی از مزایای کار با خواص ngModel، امکان استفادهی از آنها در عبارات شرطیاست که نسبت به کلاسهای CSS معرفی شدهی در ابتدای بحث، انعطاف پذیری بیشتری را به همراه خواهند داشت.
توسط ngIf میتوان المانی را به DOM اضافه و یا کلا از آن حذف کرد. در اینجا یک عبارت boolean به آن نسبت داده شدهاست. ابتدا حالت firstName.invalid را بررسی کنید. مشاهده خواهید کرد که اگر فرم برای بار اول و با مقادیر خالی نمایش داده شود، div خطا نیز ظاهر میشود که آنچنان خوشایند نیست و بهتر است خطاها را پس از اینکه کاربر مشغول به کار با فرم شد، به او نمایش دهیم؛ تا اینکه از همان ابتدا این خطاها به صورت واضحی نمایش داده شوند. بنابراین && firstName.touched نیز در اینجا اضافه شدهاست. به این ترتیب div نمایش دهندهی alert بوت استرپ، دیگر در اولین بار نمایش یک فرم خالی، ظاهر نخواهد شد. اما اگر کاربر با یک tab از فیلدی خالی رد شد، آنگاه این خطا نمایش داده میشود.
نمایش بهتر خطاهای اعتبارسنجی با مزین ساختن المانهای ورودی
علاوه بر نمایش یک alert بوت استرپی متناظر با یک فیلد غیرمعتبر، میتوان خود المانهای ورودی را نیز با شیوهنامههایی مزین ساخت.
این کار را در بوت استرپ با افزودن کلاس has-error در کنار form-group انجام میدهند. همچنین label نیز باید به کلاس control-label مزین شود تا hass-error بر روی آن نیز تاثیرگذار شود. برای پیاده سازی پویای آن در Angular به روش ذیل عمل میشود:
در اینجا روش افزودن شرطی کلاس ویژهی has-error بوت استرپ را به مجموعه کلاسهای div جاری ملاحظه میکنید. هر زمان که شرط ذکر شده برقرار باشد، در عبارت property binding مخصوص class.className، این className را به صورت خودکار به مجموعه کلاسهای آن المان اضافه میکند و برعکس.
بنابراین اگر المان firstName خالی باشد و همچنین با یک Tab از روی آن عبور کرده باشیم، کلاس has-error در کنار کلاس form-group اضافه میشود.
روش دوم: همانطور که در ابتدای بحث نیز عنوان شد، Angular بر اساس حالات مختلف یک فیلد، کلاسهای CSS خاصی را به آنها انتساب میدهد. یک چنین کاری را با مقدار دهی این کلاسها در فایل src\styles.css نیز میتوان انجام داد که دقیقا معادل بررسی خواص invalid و touched با کدنویسی است:
سایر ویژگیهای اعتبارسنجی HTML 5
تا اینجا ویژگی استاندارد required را به المان ورودی فرم ثبت اطلاعات کاربران، اضافه کردیم.
در اینجا برای مثال اعمال ویژگیهای maxlength، minlength و pattern را مشاهده میکنید. ویژگی pattern برای تعریف عبارات باقاعده بکار میرود (برای مثال، نام حتما باید با V شروع شود) و تقریبا در تمام مرورگرها (caniuse.com ) نیز پشتیبانی میشود.
برای نمونه minlength همهجا پشتیبانی نمیشود؛ اما آنرا میتوان برای مثال با الگویی مساوی "+..." جایگزین کرد.
مشکل! ذکر چند ویژگی اعتبارسنجی با هم، تداخل ایجاد میکنند!
در اینجا چون چهار ویژگی مختلف را به صورت یکجا به یک المان متصل کردهایم، اکنون div ذیل به هر کدام از این ویژگیها به صورت یکسانی واکنش نشان خواهد داد؛ زیرا خاصیت invalid را true میکنند:
روش مدیریت این حالت، به صورت ذیل است:
با یک چنین خروجی:
همانطور که در تصویر ملاحظه میکنید، محتوای خاصیت errors به صورت JSON، جهت دیباگ نیز درج شدهاست.
بنابراین وجود خاصیت firstName.errors.minlength و یا firstName.errors.pattern به این معنا است که این خطاهای خاص وجود دارند (خاصیت firstName.errors به همراه اضافاتی است) و برعکس نال بودن آنها مؤید عدم وجود خطایی است. به همین جهت میتوان به ازای هر کدام، یک div جداگانه را تشکیل داد.
مرحلهی بعد، استخراج اطلاعات بیشتری از همین شیء و محتوای خاصیت errors است. برای مثال زمانیکه در آن خاصیت minlength ظاهر شد، این خاصیت نیز دارای خاصیتی مانند requiredLength است که از آن میتوان جهت درج عدد واقعی مورد نیاز این اعتبارسنج استفاده کرد.
بهبود اعتبارسنجی drop down
در حالت فعلی تعریف drop down مثال این سری، نیازی به اعتبارسنجی نیست؛ چون لیست مشخصی از طریق کامپوننت در اختیار این المان قرار میگیرد و همواره دقیقا یکی از این عناصر انتخاب خواهند شد. اما اگر گزینهی دیگری را مانند:
به ابتدای این لیست اضافه کنیم، اینبار نیاز به اعتبارسنجی خواهد بود؛ زیرا اکنون کاربر میتواند گزینهای را انتخاب نکند و راهی پیش فرض هم برای اعتبارسنجی این گزینه وجود ندارد.
در اینجا اتصال به class.has-error را همانند مثالهای قبلی مشاهده میکنید. اما اینبار به یک خاصیت عمومی تعریف شدهی در سطح کامپوننت متصل شدهاست؛ زیرا Angular در مورد این المان خاص، کاری را برای ما انجام نخواهد داد. همچنین پیاده سازی حالت عبور از این کامپوننت با Tab نیز توسط اتصال به رخداد blur صورت گرفتهاست تا هر زمانیکه این فیلد focus را از دست داد، اجرا شود. دسترسی به مقدار جاری انتخابی این select نیز توسط یک template reference variable به نام primaryLanguage# صورت گرفتهاست. به این ترتیب میتوان به خواص این المان مانند value آن دسترسی پیدا کرد. همچنین چون میخواهیم با انتخاب گزینهی دیگری این علامت خطا رفع شود، این متد به رخداد change نیز علاوه بر blur، متصل شدهاست.
کار این متد تغییر مقدار hasPrimaryLanguageError است تا کلاس has-error در فرم نمایش داده شود. در اینجا اگر مقدار primaryLanguage انتخابی همان گزینهی default ابتدایی باشد، خاصیت hasPrimaryLanguageError به true تنظیم میشود:
اعتبارسنجی در سطح کل فرم
تا اینجا بررسیهایی را که انجام دادیم، در سطح فیلدها بودند. اکنون اگر کاربر به طور کامل تمام این فیلدها را تغییر ندهد و بر روی دکمهی ارسال کلیک کند چطور؟
زمانیکه فرم جاری را ایجاد کردیم، یک template reference variable را به نام form# نیز به آن نسبت دادیم و چون به ngForm متصل شدهاست، میتوان به خواص این شیء نیز دسترسی یافت. برای نمونه پس از دکمهی ثبت، عبارت ذیل را تعریف کنید:
همانطور که ملاحظه میکنید یکی از خواص شیء ngForm که توسط متغیر form قابل دسترسی شدهاست، خاصیت valid میباشد که حاصل اعتبارسنجی تمام عناصر داخل فرم است. برای مثال میتوان از این خاصیت جهت فعال یا غیرفعال کردن دکمهی ثبت اطلاعات نیز استفاده کرد:
در اینجا مقدار form.invalid به خاصیت disabled المان متصل شدهاست و اگر اعتبارسنجی فرم با شکست مواجه شود، این دکمه در حالت غیرفعال ظاهر میشود.
در قسمت بعد نحوهی ارسال این فرم را به سرور، بررسی میکنیم.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: angular-template-driven-forms-lab-04.zip
برای اجرای آن فرض بر این است که پیشتر Angular CLI را نصب کردهاید. سپس از طریق خط فرمان به ریشهی پروژه وارد شده و دستور npm install را صادر کنید تا وابستگیهای آن دریافت و نصب شوند. در آخر با اجرای دستور ng serve -o برنامه ساخته شده و در مرورگر پیش فرض سیستم نمایش داده خواهد شد.
کلاسهای CSS اعتبارسنجی در Angular
زمانیکه Angular فرمی را تحت نظر قرار میدهد، کلاسهای CSS خاصی را نیز بر اساس حالات عناصر مختلف آن، به آنها متصل خواهد کرد. بر این اساس میتوان ظاهر این المانها را سفارشی سازی نمود. این کلاسها به شرح زیر هستند:
کلاس CSS اعتبارسنجی | توضیحات |
ng-untouched | زمانیکه فرمی برای بار اول رندر میشود، تمام فیلدهای آن با کلاس CSS ایی به نام ng-untouched علامتگذاری میشوند. |
ng-touched | همینقدر که کاربر با یک Tab از فیلدی عبور کند، با کلاس ng-touched مزین خواهد شد. بنابراین مهم نیست که حتما دادهای وارد شده باشد یا خیر. حتی عبور از یک فیلد نیز به معنای لمس آن نیز میباشد. |
ng-pristine | مربوط به زمانیاست که یک فیلد نه تغییر کردهاست و نه لمس شدهاست. |
ng-dirty | همینقدر که کاربر، تغییری را در فیلدی ایجاد کند، آن المان با کلاس ng-dirty مشخص خواهد شد. |
ng-valid | برای حالت موفقیت آمیز بودن اعتبارسنجی، به آن المان انتساب داده میشود. |
ng-invalid | برای حالت غیر موفقیت آمیز بودن اعتبارسنجی، به آن المان انتساب داده میشود. |
برای اینکه بتوانیم این موارد را در عمل مشاهده کنیم، به ابتدای فرم مثال این سری، تغییرات ذیل را اعمال خواهیم کرد:
<div class="form-group"> <label>First Name</label> <input #firstName required type="text" class="form-control" name="firstName" [(ngModel)]="model.firstName"> </div> <h3>Classes</h3> <h4>{{ firstName.className }}</h4>
تصویر فوق کلاسهایی را نمایش میدهد که در اولین بار نمایش فرم، به المان firstName متصل شدهاند. برای مثال در این حالت کلاس ng-pristine قابل مشاهدهاست و هنوز تغییری در آن حاصل نشدهاست.
در ادامه اگر حرفی را به آن اضافه کنیم:
هنوز هم ng-untouched آن برقرار است؛ اما ng-pristine آن به ng-dirty تبدیل شدهاست. در اینجا حتی اگر کل اطلاعات فیلد را نیز حذف کنیم و آنرا خالی کنیم یا به حالت اول بازگردانیم نیز کلاس ng-dirty قابل مشاهدهاست. بنابراین اگر حالت فیلدی dirty شد، همواره به همین حالت باقی میماند.
در این لحظه اگر با Tab به فیلد دیگری در فرم مراجعه کنیم:
در اینجا است که کلاس ng-untouched به ng-touched تبدیل میشود. بنابراین کلاسهای مختلف لمس یک فیلد، ارتباطی به افزوده شدن یا حذف کاراکتری از یک فیلد ندارند و فقط به از دست رفتن focus و مراجعهی به فیلد دیگری مرتبط میشوند.
اگر به المان تغییر یافتهی فوق دقت کنید، ویژگی required نیز به آن اضافه شدهاست (علاوه بر template reference variable ایی که تعریف کردیم). در این حالت کل فیلد را خالی کنید:
همانطور که مشاهده میکنید، اکنون کلاس ng-valid به کلاس ng-invalid تغییر یافتهاست.
ارتباط بین کلاسهای CSS اعتبارسنجی و خواص ngModel
تمام کلاسهای -ng ایی که در بالا معرفی شدند، معادلهای خواص ngModel ایی نیز دارند. فقط کافی است -ng آنها را حذف کنید، باقیماندهی آن، نام خاصیت متناظری در ngModel خواهد بود. برای مثال کلاس ng-untouched به خاصیت untouched نگاشت میشود و به همین ترتیب برای مابقی.
template reference variable ایی را که تا به اینجا به المان اضافه کردیم (firstName#) به خواص همان المان دسترسی دارد (مانند className آن). اما در ادامه میخواهیم این متغیر به ngModel و خواص آن دسترسی داشته باشد و میدان دید آن تغییر کند. به همین جهت تنها کافی است تا ngModel را به این متغیر انتساب دهیم:
<div class="form-group"> <label>First Name</label> <input #firstName="ngModel" required type="text" class="form-control" name="firstName" [(ngModel)]="model.firstName"> </div> <h4>dirty: {{ firstName.dirty }}</h4>
یک نکته: در حالت خواص valid و invalid که مرتبط با اعتبارسنجی هستند، خاصیت سومی نیز به نام errors وجود دارد که حاوی اطلاعات بیشتری در مورد خطای اعتبارسنجی رخ دادهاست. بنابراین وجود این خاصیت و نال نبودن آن نیز دلالت بر وجود یک خطای اعتبارسنجی است. از خاصیت errors در ادامهی بحث در قسمت «مدیریت چندین خطای همزمان اعتبارسنجی» استفاده خواهیم کرد.
نمایش بهتر خطاهای اعتبارسنجی با بررسی خواص ngModel
یکی از مزایای کار با خواص ngModel، امکان استفادهی از آنها در عبارات شرطیاست که نسبت به کلاسهای CSS معرفی شدهی در ابتدای بحث، انعطاف پذیری بیشتری را به همراه خواهند داشت.
<div class="form-group"> <label>First Name</label> <input #firstName="ngModel" #firstNameElement required type="text" class="form-control" name="firstName" [(ngModel)]="model.firstName"> <div *ngIf="firstName.invalid && firstName.touched" class="alert alert-danger"> First Name is required. </div> </div> <h4>className: {{ firstNameElement.className }}</h4> <h4>dirty: {{ firstName.dirty }}</h4> <h4>invalid: {{ firstName.invalid }}</h4>
نمایش بهتر خطاهای اعتبارسنجی با مزین ساختن المانهای ورودی
علاوه بر نمایش یک alert بوت استرپی متناظر با یک فیلد غیرمعتبر، میتوان خود المانهای ورودی را نیز با شیوهنامههایی مزین ساخت.
این کار را در بوت استرپ با افزودن کلاس has-error در کنار form-group انجام میدهند. همچنین label نیز باید به کلاس control-label مزین شود تا hass-error بر روی آن نیز تاثیرگذار شود. برای پیاده سازی پویای آن در Angular به روش ذیل عمل میشود:
<div class="form-group" [class.has-error]="firstName.invalid && firstName.touched"> <label class="control-label">First Name</label>
بنابراین اگر المان firstName خالی باشد و همچنین با یک Tab از روی آن عبور کرده باشیم، کلاس has-error در کنار کلاس form-group اضافه میشود.
روش دوم: همانطور که در ابتدای بحث نیز عنوان شد، Angular بر اساس حالات مختلف یک فیلد، کلاسهای CSS خاصی را به آنها انتساب میدهد. یک چنین کاری را با مقدار دهی این کلاسها در فایل src\styles.css نیز میتوان انجام داد که دقیقا معادل بررسی خواص invalid و touched با کدنویسی است:
.ng-touched.ng-invalid{ border: 1px solid red; }
سایر ویژگیهای اعتبارسنجی HTML 5
تا اینجا ویژگی استاندارد required را به المان ورودی فرم ثبت اطلاعات کاربران، اضافه کردیم.
<input #firstName="ngModel" #firstNameElement required maxlength="3" minlength="2" pattern="^V.*" type="text" class="form-control" name="firstName" [(ngModel)]="model.firstName">
برای نمونه minlength همهجا پشتیبانی نمیشود؛ اما آنرا میتوان برای مثال با الگویی مساوی "+..." جایگزین کرد.
مشکل! ذکر چند ویژگی اعتبارسنجی با هم، تداخل ایجاد میکنند!
در اینجا چون چهار ویژگی مختلف را به صورت یکجا به یک المان متصل کردهایم، اکنون div ذیل به هر کدام از این ویژگیها به صورت یکسانی واکنش نشان خواهد داد؛ زیرا خاصیت invalid را true میکنند:
<div *ngIf="firstName.invalid && firstName.touched" class="alert alert-danger"> First Name is required. </div>
<div class="form-group" [class.has-error]="firstName.invalid && firstName.touched"> <label class="control-label">First Name</label> <input #firstName="ngModel" #firstNameElement required maxlength="3" minlength="2" pattern="^V.*" type="text" class="form-control" name="firstName" [(ngModel)]="model.firstName"> <div *ngIf="firstName.invalid && firstName.touched"> <div class="alert alert-info"> errors: {{ firstName.errors | json }} </div> <div class="alert alert-danger" *ngIf="firstName.errors.required"> Name is required. </div> <div class="alert alert-danger" *ngIf="firstName.errors.minlength"> Name should be minimum {{firstName.errors.minlength.requiredLength}} characters. </div> <div class="alert alert-danger" *ngIf="firstName.errors.maxlength"> Name should be max {{firstName.errors.maxlength.requiredLength}} characters. </div> <div class="alert alert-danger" *ngIf="firstName.errors.pattern"> Name pattern: {{firstName.errors.pattern.requiredPattern}} </div> </div> </div>
همانطور که در تصویر ملاحظه میکنید، محتوای خاصیت errors به صورت JSON، جهت دیباگ نیز درج شدهاست.
بنابراین وجود خاصیت firstName.errors.minlength و یا firstName.errors.pattern به این معنا است که این خطاهای خاص وجود دارند (خاصیت firstName.errors به همراه اضافاتی است) و برعکس نال بودن آنها مؤید عدم وجود خطایی است. به همین جهت میتوان به ازای هر کدام، یک div جداگانه را تشکیل داد.
مرحلهی بعد، استخراج اطلاعات بیشتری از همین شیء و محتوای خاصیت errors است. برای مثال زمانیکه در آن خاصیت minlength ظاهر شد، این خاصیت نیز دارای خاصیتی مانند requiredLength است که از آن میتوان جهت درج عدد واقعی مورد نیاز این اعتبارسنج استفاده کرد.
بهبود اعتبارسنجی drop down
در حالت فعلی تعریف drop down مثال این سری، نیازی به اعتبارسنجی نیست؛ چون لیست مشخصی از طریق کامپوننت در اختیار این المان قرار میگیرد و همواره دقیقا یکی از این عناصر انتخاب خواهند شد. اما اگر گزینهی دیگری را مانند:
<option value="default">Select a Language...</option>
<div class="form-group" [class.has-error]="hasPrimaryLanguageError"> <label class="control-label">Primary Language</label> <select class="form-control" name="primaryLanguage" #primaryLanguage (blur)="validatePrimaryLanguage(primaryLanguage.value)" (change)="validatePrimaryLanguage(primaryLanguage.value)" [(ngModel)]="model.primaryLanguage"> <option value="default">Select a Language...</option> <option *ngFor="let lang of languages"> {{ lang }} </option> </select> </div>
export class EmployeeRegisterComponent { hasPrimaryLanguageError = false; validatePrimaryLanguage(value) { if (value === 'default'){ this.hasPrimaryLanguageError = true; } else{ this.hasPrimaryLanguageError = false; } } }
اعتبارسنجی در سطح کل فرم
تا اینجا بررسیهایی را که انجام دادیم، در سطح فیلدها بودند. اکنون اگر کاربر به طور کامل تمام این فیلدها را تغییر ندهد و بر روی دکمهی ارسال کلیک کند چطور؟
<form #form="ngForm" novalidate>
<h3> form.valid: {{ form.valid }}</h3>
<button class="btn btn-primary" type="submit" [disabled]="form.invalid">Ok</button>
در قسمت بعد نحوهی ارسال این فرم را به سرور، بررسی میکنیم.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: angular-template-driven-forms-lab-04.zip
برای اجرای آن فرض بر این است که پیشتر Angular CLI را نصب کردهاید. سپس از طریق خط فرمان به ریشهی پروژه وارد شده و دستور npm install را صادر کنید تا وابستگیهای آن دریافت و نصب شوند. در آخر با اجرای دستور ng serve -o برنامه ساخته شده و در مرورگر پیش فرض سیستم نمایش داده خواهد شد.
بازخوردهای دوره
صفحات مودال در بوت استرپ 3
فکر نمیکنم اشکال از layout باشه چون پروژه که داشته کارشو میکرده من فقط دو تا جاوا اسکریپت دیگه به آخرش اضافه کردم ، این layout منه :
. . . <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title> .... </title> @Styles.Render("~/Content/css") @Scripts.Render("~/bundles/modernizr") <!--This bundle was moved by the Telerik VS Extensions for compatibility reasons--> @Scripts.Render("~/bundles/jquery") <link href="@Url.Content("~/Content/kendo/2013.3.1324/kendo.common.min.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/kendo/2013.3.1324/kendo.dataviz.min.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/kendo/2013.3.1324/kendo.bootstrap.min.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/kendo/2013.3.1324/kendo.dataviz.bootstrap.min.css")" rel="stylesheet" type="text/css" /> <link href="@Url.Content("~/Content/kendo/2013.3.1324/kendo.rtl.min.css")" rel="stylesheet" type="text/css" /> <script src="@Url.Content("~/Scripts/kendo/2013.3.1324/jquery.min.js")"></script> <script src="@Url.Content("~/Scripts/kendo/2013.3.1324/kendo.all.min.js")"></script> <script src="@Url.Content("~/Scripts/kendo/2013.3.1324/kendo.aspnetmvc.min.js")"></script> <script src="@Url.Content("~/Scripts/kendo.modernizr.custom.js")"></script> </head> <body> . . . . . @Scripts.Render("~/bundles/bootstrap") <script src="@Url.Content("~/Scripts/kendo/2013.3.1324/jquery.min.js")"></script> <script src="@Url.Content("~/Scripts/kendo/2013.3.1324/kendo.all.min.js")"></script> <script src="@Url.Content("~/Scripts/kendo/2013.3.1324/kendo.aspnetmvc.min.js")"></script> <script src="@Url.Content("~/Scripts/kendo.modernizr.custom.js")"></script> <script src="@Url.Content("~/Scripts/jquery.bootstrap-modal-ajax-form.js")"></script> <script src="@Url.Content("~/Scripts/jquery.bootstrap-modal-confirm.js")"></script> @RenderSection("scripts", required: false) </body> . . .
چندی پیش یکی از دوستان درباره فریم ورک ExtJs سوالاتی را پرسیده بود که تصمیم گرفتم جوابهای مورد نظر را به صورت عمومی در قالب یک پست منتشر کنم.
پاسخ یک کلمه است: ExtJs. بله درست است در طراحی این CMS تنها از یک فریم ورک جاوااسکریپتی به نام ExtJs استفاده شده است. فریم ورکی که به عقیده بعضیها یک رویا برای توسعه دهندگان وب است و به عقیده سایرین شاید یک کابوس. در این پست قصد دارم به عنوان کسی که با این فریم ورک آشنایی دارم این موضوع را بررسی و مزایا و معایب این فریم ورک را عنوان کنم.
ExtJs یک فریم ورک جاوااسکریپ است بر مبنای Sencha و طراحی شده برای توسعه پروژههای وب در مقیاس بزرگ و به صورت cross-platform . مجوز استفاده از این فریم ورک به صورت GPLv3 است.(یعنی مجاز به استفاده رایگان از فایلهای این فریم ورک هستید به شرطی که قصد استفاده تجاری از پروژه تهیه شده را نداشته باشید! در غیر این صورت باید زحمت خرید نسخه تجاری این فریم ورک را متحمل شوید).
نسخه ای که درباره آن بحث میکنیم نسخه چهار این فریم ورک (ExtJs 4) که بر مبنای ExtJs 3 تولید شده است. تفاوت عمده آن با نسخه قبلی در تکمیل ابزار و کامپوننت هاست و از طرفی نسخه چهار این فریم ورک بر مبنای مدل MVC توسعه داده شده است. یعنی همانند Angular و BackBoneJs میتوانید مفاهیم کنترلر و مدل را به راحتی پیاده سازی کنید.
رویایی به نام ExtJs
اگر بخواهیم این فریم ورک را یک رویا برای توسعه دهندگان وب بنامیم میتوان عناوین زیر را به عنوان مزایا برشمرد:
اجرای کد بالا با استفاده از ExtJs به صورت زیر خواهد بود:
خروجی مورد نظر برای Ext.Net:
با توجه مواردی که ذکر شد میتوان به یک نکته مهم رسید و آن هم این است که هنگام انتخاب ExtJs یا Ext.Net (البته این شامل اکثر ابزارهای توسعه دیگر نیز خواهد شد) حتما شرایط موجود و حاکم برای توسعه محصول را مد نظر داشته باشید که این شرایط شامل محیط اجرای محصول، مدت زمان لازم برای توسعه، سطح دانش نیرویهای توسعه دهنده و ... نیز میباشد.
- ExtJs چیست؟
- چه زمانی کاربرد دارد؟
- تفاوت آن با سایر فریم ورکهای جاوااسکریپ در چیست؟
پاسخ یک کلمه است: ExtJs. بله درست است در طراحی این CMS تنها از یک فریم ورک جاوااسکریپتی به نام ExtJs استفاده شده است. فریم ورکی که به عقیده بعضیها یک رویا برای توسعه دهندگان وب است و به عقیده سایرین شاید یک کابوس. در این پست قصد دارم به عنوان کسی که با این فریم ورک آشنایی دارم این موضوع را بررسی و مزایا و معایب این فریم ورک را عنوان کنم.
ExtJs یک فریم ورک جاوااسکریپ است بر مبنای Sencha و طراحی شده برای توسعه پروژههای وب در مقیاس بزرگ و به صورت cross-platform . مجوز استفاده از این فریم ورک به صورت GPLv3 است.(یعنی مجاز به استفاده رایگان از فایلهای این فریم ورک هستید به شرطی که قصد استفاده تجاری از پروژه تهیه شده را نداشته باشید! در غیر این صورت باید زحمت خرید نسخه تجاری این فریم ورک را متحمل شوید).
نسخه ای که درباره آن بحث میکنیم نسخه چهار این فریم ورک (ExtJs 4) که بر مبنای ExtJs 3 تولید شده است. تفاوت عمده آن با نسخه قبلی در تکمیل ابزار و کامپوننت هاست و از طرفی نسخه چهار این فریم ورک بر مبنای مدل MVC توسعه داده شده است. یعنی همانند Angular و BackBoneJs میتوانید مفاهیم کنترلر و مدل را به راحتی پیاده سازی کنید.
رویایی به نام ExtJs
اگر بخواهیم این فریم ورک را یک رویا برای توسعه دهندگان وب بنامیم میتوان عناوین زیر را به عنوان مزایا برشمرد:
- در درجه اول قابلیتی که این فریم ورک را متفاوت از سایر فریم ورکهای جاوااسکریپتی میکند
این است که این فریم ورک انبوهی از کامپوننتها و ویجیتهای آماده را به
همراه خود دارد (با کارایی و انعطاف پذیری قابل قبول) و به نوعی شما را بی نیاز از هرگونه مجموعه کامپوننتهای دیگر خواهد
کرد.
- این فریم ورک به خوبی از مباحت OOP پشتیبانی میکند و به این صورت است که یک
سری مفاهیم و مدلهای پایه در این فریم ورک تعبیه شده و به راحتی شما میتوانید مدلهای مورد نظر خود را بر اساس این مفاهیم و مدلهای پایه توسعه
دهید.
- تمام مفاهیم و ابزار لازم جهت درخواستهای Ajax ای و اعتبار سنجی سفارشی و
دستکاری عناصر DOM و... به خوبی در این فریم ورک وجود دارد.
- به دلیل وجود کامپوننتهای یک دست و آماده به راحتی میتوانید امکان تغییر theme را در پروزههای خود بدون کوچکترین زحمت قرار دهید.
- کنترل GridPanel،TreeView ، کنترلهای ورود اطلاعات، کنترل Tab با قابلیت درخواستهای لود صفحات به صورت Ajax و Async با کمترین زحمت در کد نویسی و هم چنین چارتهای بسیار گسترده و متنوع از دیگر مزایای این فریم ورک میتواند باشد.
- ارائه مکانیزمی مناسب برای کار با عملیات داده ای Json. به عنوان نمونه:
Ext.data.JsonP.request({ url: '@url', params: { apiKey: '1234' }, callbackKey: 'myCallbackFn', success: function(){ }, failure: function(){ }, scope: this });
- این فریم ورک ابزارهای جالب و کارآمدی برای توسعه به صورت SPA را داراست.
- کنترلهای داده ای این فریم ورک در هنگام کار با حجم داده بسیار زیاد، فراتر از انتظار عمل میکنند(برای مثال کنترل GridPanel و DataView)
- اگر قصد تولید و توسعه بک پروژه بزرگ درون سازمانی را دارید و سرعت تولید نیز برای شما مهم است ExtJs در این زمینه کمک شایانی به شما خواهد کرد.
- و...
حال با همه این تفاسیر آیا این فریم ورک یک رویا برای هر توسعه دهنده وب خواهد بود؟
به طور قطع نه. با توجه به اصل واقع بینی! همواره به خاطر داشته باشید که
اگر این فریم ورک یک ابزار بی نقص و همه منظوره بود الآن مطمئنا صدها کتاب و
مستندات درباره آن نوشته شده بود و شاید شهرتی بس فراتر از این داشت.
کابوسی به نام ExtJs
- اگر قصد ایجاد یک وب سایت کوچک و جمع و جور را دارید به طوری که مباحث مربوط به SEO نیز برای شما اهمیت دارد تجربه نشان داده است که انتخاب ExtJs میتواند یکی از بزرگترین اشتباهات در طول عمر کاری شما شود.
- ExtJs هیچ گونه کمکی برای تولید و توسعه اپلیکیشنهای موبایل یا پروژههای وب گرافیکی نمیتواند به شما کند.
- اگر سرعت یکی از فاکتور خیلی مهم برای شماست بهتر است به این فریم ورک علاقه نشان ندهید.(کتابخانه آن چیزی در حدود 500KB است! البته با فشرده سازی به 150KB خواهد رسید که باز هم قابل قبول نیست)
- مجوز استفاده برای پروژههای تجاری به صورت رایگان نیست.(^)
- به دلیل وجود ابزارهای متنوع و زیاد؛ زمان یادگیری برای آشنایی و کار کردن با ابزارها، نسبتا طولانی خواهد شد.
- کد نویسی برای استفاده از ابزارهای آن در مقایسه با Jquery و Angular بیشتر خواهد بود(البته این به نوعی مزیت هم است، به دلیل اینکه خوانایی کدها بسیار بالا میرود)
- در طراحی کامپوننتها آن از تگ div در حد غیر قابل قبول استفاده شده است به طوری که Debug صفحات حتی با Firebug هم در بعضی مواقع سخت میشود.
- و...
Ext.Net چیست؟
Ext.Net یک پیاده سازی خاص از فریم ورک ExtJs است که برای توسعه پروژههای Asp.Net Web Forms و Asp.Net MVC طراحی شده است. تفاوت اصلی بین این دو محصول در نوع کدنویسی برای استفاده در پروژههای Asp.Net است. برای مثال در هنگام کار با Ext.Net و پروژههای MVC از آنجا که این محصول سازگاری کامل با موتور Razor دارد به راحتی میتوانید به صورت سینتکس Razor صفحات خود را طراحی کنید.
مثال:
ExtJs
Ext.create('Ext.panel.Panel', { title: 'Fit Layout', width: 500, height: 200, items: { title: 'Inner Panel', html: 'Panel content', bodyPadding: 10, border: true }, renderTo: Ext.getBody() });
Ext.Net
@(X.Panel() .ID("ExpandablePanel") .Title("Panel") .Width(500) .Height(300) .Collapsible(true) .Loader(X.ComponentLoader() .Url(Url.Action("RenderChild")) .Mode(LoadMode.Frame) .DisableCaching(true) .Params(new { containerId = "ExpandablePanel" }) .LoadMask(lm => lm.ShowMask = true) ) .Listeners(l => { l.Expand.Handler = "this.reload();"; l.Collapse.Handler = "this.clearContent();"; }) )
جمع بندی:
با توجه مواردی که ذکر شد میتوان به یک نکته مهم رسید و آن هم این است که هنگام انتخاب ExtJs یا Ext.Net (البته این شامل اکثر ابزارهای توسعه دیگر نیز خواهد شد) حتما شرایط موجود و حاکم برای توسعه محصول را مد نظر داشته باشید که این شرایط شامل محیط اجرای محصول، مدت زمان لازم برای توسعه، سطح دانش نیرویهای توسعه دهنده و ... نیز میباشد.