اشتراکها
در T-SQL 2012 قابلیت صفحه بندی، نمایش خروجی یک Query فراهم گردیده است، که برای نرم افزارهای تحت وب بسیار پرکاربرد میباشد، به عنوان مثال، از جمله کاربردهای بارز آن، میتوان به نمایش نتیجه یک جستجو بصورت صفحه بندی با تعداد رکورد محدود،اشاره نمود.
مایکروسافت برای ایجاد قابلیت صفحه بندی و محدود نمودن نمایش خروجی یک Query، تغییراتی را در Syntax مربوط به Order by ایجاد نموده است، که در ذیل مشاهده مینمایید:
ORDER BY order_by_expression [ COLLATE collation_name ] [ ASC | DESC ] [ ,...n ] [ <offset_fetch> ] <offset_fetch> ::= { OFFSET { integer_constant | offset_row_count_expression } { ROW | ROWS } [ FETCH { FIRST | NEXT } {integer_constant | fetch_row_count_expression } { ROW | ROWS } ONLY ] }
OFFSET (نقطه شروع) : شامل یک پارامتر است،بطوریکه،پارامتر فوق میتواند یک عدد (integer_constant) یا یک عبارت (offset_row_count_expression) بپذیرد. در اینجا منظور از عبارت میتواند یک Subquery باشد، که خروجی آن فقط یک مقدار عددی است. یا یک متغیر و غیرو...
در مورد ROW یا ROWS باید بگویم باهم فرقی ندارند.
FETCH : همانند OFFSET شامل یک پارامتر است، و پارامتر آن میتواند یک عدد یا عبارت بپذیرد.
Next یا First نیز با هم تفاوتی ندارند و جهت سازگاری با ANSI میباشند.
OFFSET : در وافع تعداد سطر قابل حذف، پیش از نمایش اولین سطر در خروجی را بیان میکند.
FETCH : بیانگر تعداد رکورد قابل نمایش در یک صفحه میباشد.
برای درک بیشتر مثالی میزنیم:
ابتدا بوسیله Script زیر یک جدول ایجاد مینماییم، سپس چند رکورد درون آن درج میکنیم:
Create Table Testoffset (BusinessEntityID int, FirstName varchar(100) , LastName varchar(100) ); Insert into Testoffset (BusinessEntityID,FirstName,LastName) Values(1,'Ken','Sánchez') ,(2,'Terri','Duffy') ,(3,'Roberto','Tamburello') ,(4,'Rob','Walters') ,(5,'Gail','Erickson') ,(6,'Jossef','Goldberg') ,(7,'Dylan','Miller') ,(8,'Diane','Margheim') ,(9,'Gigi','Matthew') ,(10,'Michael','Raheem')
در ادامه Script زیر را اجرا نمایید، تا تعداد رکوردهای درج شده را مشاهده کنید:
در شکل، سه سطر (منظور رکورد 4و5و6) در کادر قرمز رنگ دیده میشود، میخواهیم Script ی ایجاد نماییم، که فقط سه سطر فوق را نمایش دهد. بنابراین خواهیم داشت:
SELECT BusinessEntityID, FirstName, LastName FROM Testoffset ORDER BY BusinessEntityID OFFSET 3 ROWS FETCH First 3 ROWS only
خروجی:
اگر به Query اجرا شده دقت کنیم. در قسمت Order By جلوی Offset مقدار 3 اختصاص داده شده بود، یعنی نقطه شروع از سطر چهارم میباشد، به عبارت دیگر مقداری که به Offset اختصاص داده میشود، به SQL Server میفهماند،چه تعداد رکورد را نمایش ندهد. اگر شکل اول و دوم را با هم مقایسه نمایید، براحتی متوجه میشوید که OFFSET نقطه شروع را مشخص کرده است.
مقداریکه برای Fetch در نظر گرفته شده بود برابر 3 است، که بیانگر تعداد سطر نمایش داده شده در خروجی از نقطه آغازین (offset) میباشد.
امیدوارم مفید واقع شده باشد.
نظرات مطالب
EF Code First #5
با سلام؛ لطفا اگه مقدوره دستورات sql که در روش code first استفاده میشه را هم توضیح بدین. مثل: select-fine- where, ...
یکی از محصولات پرکاربرد و حرفه ای مایکروسافت در زمینه تولید گزارش SQL Server Reporting Services یا به اختصار SSRS میباشد . در این پست نحوه ایحاد یک گزارش ساده به صورت والد و فرزندی ، انتشار گزارش روی وب سرور و مدیریت نمایش ستونها با استفاده از Expressionها را در محیط BIDS بیان میکنم
برای انجام این پروسه ، از ابزار BIDS استفاده خواهیم کرد . همچنین برای اطلاعات و دادهها از دیتابیس آزمایشی Adventure works استفاده میکنیم (دانلود )
صورت مسئله : گزارش از دپارتمانهای کاری و تعداد کارمندان مرد و زن هر دپارتمان . که با کلیک روی هر سطر گزارش (بسته به جنسیت) بتوان لیست تمام افراد آن دپارتمان را دید .
بخش اول :
برای شروع BIDS را باز کرده و یک پروژه از نوع Report Server Project استارت بزنید .
نام این پروژه را در اینجا introductionPrj1 قرار دادم .
همانطور که ملاحظه میکنید ، سه پوشه در Solution explorer قرار دارد که برای تعریف پایگاه داده با پوشه Shared Data Sources و برای تعریف گزارشات از پوشه Reports استفاده خواهیم کرد
برای این منظور ابتدا یک data source تعریف میکنیم :
و سپس شروع به ساختن یک گزارش میکنیم :
مراحل را تا رسیدن به مرحله تعریف Query پی میگیریم .
انتخاب دیتا سورس :
در اینجا میخواهیم قسمت اول گزارش یعنی فهرست کردن تعداد کارمندان هر دپارتمان را به تفکیک جنسیت مشاهده کنیم :
SELECT DEPARTMENTNAME, GENDER, COUNT(1) AS COUNT FROM DBO.DIMEMPLOYEE GROUP BY DEPARTMENTNAME,GENDER ORDER BY DEPARTMENTNAME,GENDER
برای مشاهده صحت دستور میتوانید از Query Builder کمک بگیرید :
ادامه تنظیمات را مانند تصویر پی بگیرید (تعریف Tabular بودن گزارش و طراحی جدول و theme و نام گذاری گزارش )
به این ترتیب بخش اول گزارش ایجاد شد . حال باید زیر گزارش مربوطه را ایجاد کنیم :
مجددا مراحل را برای ساخت یک گزارش جدید پیگیری کنید و برای دستور کوئری از دستور زیر استفاده کنید :
SELECT EMPLOYEEKEY,FIRSTNAME,LASTNAME, MIDDLENAME,TITLE,HIREDATE, BIRTHDATE,EMAILADDRESS,PHONE,GENDER FROM DBO.DIMEMPLOYEE WHERE DEPARTMENTNAME=@DEPARTMENTNAME AND GENDER=@GENDER
و تست گزارش :
و بقیه قسمتها مانند قبل :
تا به این مرحله data source و گزارشها ایجاد شدند :
اکنون باید ارتباط بین دو گزارش را برقرار کنیم :
گزارش والد را باز کرده و روی ستون COUNT کلیک راست نموده و گزینه Popperties را انتخاب نمایید :
سپس در تب action گزینه Go to Report را انتخاب نموده و گزارش فرزند را انتخاب نمایید .
در انتها هم باید پارامترها را تعریف کنید . خروجی مانند زیر خواهد بود :
ToolTip از تب General قابل اعمال است .
و در نهایت با کلیک روی این سطر میتوانید گزارش مرتبط را مشاهده کنید :
تا به این مرحله گزارش تکمیل شد که البته برای ظاهر آن هم باید فکری کرد که در این پست اشاره ای نمیشود .
بخش دوم :
گزارش جاری فقط قابل استفاده از طریق BIDS است و با توجه به محدودیت دسترسی باید آن را در جایی قرار داد تا کاربران بتوانند از آن استفاده کننده . برای این منظور باید تنظیمات SSRS Web Application انجام شود تا بتواند روی سرور عملیاتی قرار گیرد .
در صورتی که تنظیمات SSRS برای قرار گرفتن روی وب سرور انجام نشده باشد و ما بخواهیم گزارش را Deploy کنیم خطا دریافت خواهیم کرد .
پس در ادامه نحوه تنظیم وب سرور را بیان میکنم و پس از آن گزارش را روی وب سرور قرار میدهیم :
برای این منظور باید برنامه Reporting Services Configuration Manager که در مسیر نصب SQL Server است برویم
پس از اتصال به سرور به تب Report Manager Url بروید :
در این مرحله باید سرور را تنظیم کنید تا بتوانیم پروژه را روی آن Deploy کنیم . از باز بودن پورت اطیمنان حاصل کنید . سپس وب سرویس را تنظیم کنید که هر دو فقط شامل نام Virtual Directory و Credential آن میشود . (مگر اینکه تنظیمات خاصی داشته باشید).
در صورت اجرا کردن مسیر URL باید بتوانید صفحه خانگی آن را مشاهده کنید :
که البته هنوز هیچ گزارشی روی آن قرار نگرفته است .سپس به گزارش خود باز میگردیم تا تنظیمات سرور را روی BIDS تکمیل کنیم :
برای این منظور روی پروژه کلیک راست کنید و ابتدا روی Properties کلیک کنید .
تنظمات مهم شامل مسیر سرور که برابر با همان سرویسی است که تنظیم کرده اید و مسیر پوشه ای که گزارشها روی سرور در آن قرار خواهند گرفت ، میباشد.دقت کنید که باید حتما پوشه موجود باشد . اگر به حالت پیشفرش رها کنید ، گزارشات در Root قرار خواهند گرفت .
روی OK کلیک کنید و پروژه را Deploy کنید .
اگر به سایت برگردید ، گزارشات را میتوانید مشاهده کنید
بخش سوم :
در این مرحله میخواهیم یکی از ویژگی هایی که در گزارش گیری کاربرد زیادی دارد ، یعنی نمایش ستونهای دلخواه در گزارش را به کمک SSRS و BIDS به کار ببریم.
برای این منظور به پنجره Report Data مراجعه کرده و روی Parameters کلی راست کرده و گزینه Add Parameter را انتخاب کنید :
فیلدها را مانند زیر پر کنید : (در اینجا میخواهیم یک dropdown به کاربر نشان داده شود تا انتخاب کند که ستون نمایش داده شود یا خیر . همچنین مقدار پیشفرض بله است)
گزینههای مورد نظر را انتخاب نمایید
و تعیین مقدار پیش فرض
و نتیجه در BIDS :
اکنون باید تغییر مقدار این ستون را بر روی گزارش اعمال کنیم :
برای همین منظور روی ستون BirthDate در حالت Design کلیک راست کرده و گزینه Column Visibility را انتخاب کنید :
سپس باید تنظیم کنیم که در نمایش و عدم نمایش این ستون باید بر اساس یک عبارت یا expression باشد .
عبارت زیر را وارد کنید (به این معنی که اگر مقدار 1 بود نمایش داده شود در غیر این صورت نمایش داده نشود) برای اطلاعات بیشتر در مورد دستورات Expression به اینجا و اینجا و اینجا مراجعه کنید
=iif(Parameters!ShowBirthDate.Value=1,true,false)
اکنون میتوانید گزارش را deploy کنید و تنظیمات سطوح دسترسی کاربران را انجام دهید
پیشنهادها
استفاده از spatial data در EF
پشتیبانی از spatial data به EF 5 اضافه شد. نیاز است به کمک مآخذ ذیل، یک مطلب جدید در مورد آن تهیه شود:
- Basic Spatial Data with SQL Server and Entity Framework 5.0
- Using spatial data types with Entity Framework 5.0
- Using Spatial Data with SQL Server 2012, Entity Framework 5 and ASP.NET MVC
- Spatial Data Type Support in Entity Framework 5
- Using Spatial Data in ASP.Net MVC with SQL Server 2012, Entity Framework 5 and Infragistics jQuery Map
- Spatial Data and the Entity Framework
- Spatial data and Entity Framework - from real world usage
- Entity Framework Spatial Part 1: Loading data
- Spatial Data type support in Entity Framework 5.0
- Creating a Geometry Point in Entity Framework
- Spatial - Code First
- Spatial Types in the Entity Framework
- How To: Using spatial data with Entity Framework and Connector/Net
در قسمت قبل، پیشنیازهای کار با AngularJS 2.0 مرور و دریافت شدند. اگر مطالب آنرا پیگیری کرده باشید، هم اکنون باید در پوشهی node_modules واقع در ریشهی پروژه، تمام اسکریپتهای لازم جهت شروع به کار با AngularJS 2.0 موجود باشند.
تعاریف مداخل فایل index.html یک سایت AngularJS 2.0
پروژهای که در اینجا در حال استفاده است یک برنامهی ASP.NET MVC 5.x است؛ اما الزامی هم به استفادهی از آن وجود ندارد. یا یک فایل index.html را به ریشهی پروژه اضافه کنید و یا فایل Views\Shared\_Layout.cshtml را به نحو ذیل تغییر دهید:
در اینجا ابتدا تعاریف مداخل بوت استرپ و cssهای سفارشی برنامه را مشاهده میکنید.
سپس کتابخانههای جاوا اسکریپتی مورد نیاز جهت کار با AngularJS 2.0 به ترتیبی که ذکر شده، باید تعریف شوند.
ذکر /~ در ابتدای آدرسها، مختص به ASP.NET MVC است. اگر از آن استفاده نمیکنید، نیازی به ذکر آن هم نیست.
در ادامه تعاریف System.JS ذکر شدهاست. System.JS کار بارگذاری ماژولهای برنامه را به عهده دارد. به این ترتیب دیگر نیازی نیست تا به ازای هر قسمت جدید برنامه، مدخلی را در اینجا اضافه کرد و کار بارگذاری آنها خودکار خواهد بود. فرمت register ایی که در اینجا ذکر شدهاست، تا ماژولهای استاندارد با فرمت ES 6 را نیز پشتیبانی میکند. همچنین با ذکر و تنظیم پسوند پیش فرض به js، دیگر نیازی نخواهد بود تا در حین تعریف importها در قسمتهای مختلف برنامه، پسوند فایلها را به صورت صریح ذکر کرد. مبحث improtها مرتبط است به مفاهیم ماژولها در ES 6 و همچنین TypeScript.
سطر System.import کار بارگذاری اولین ماژول برنامه را از پوشهی app قرار گرفته در ریشهی سایت انجام میدهد. این ماژول main نام دارد.
نوشتن اولین کامپوننت AngularJS 2.0
برنامههای AngularJS 2.0 متشکل هستند از تعدادی کامپوننت و سرویس:
و هر کامپوننت تشکیل شدهاست از:
- یک قالب یا Template: با استفاده از HTML تعریف میشود و کار تشکیل View و نحوهی رندر کامپوننت را مشخص میکند. در این Viewها با استفاده از امکانات binding و directives موجود در AngularJS 2.0 کار دسترسی به دادهها صورت میگیرد.
- یک کلاس: کار این کلاس که توسط TypeScript تهیه میشود، فراهم آوردن کدهای مرتبط با قالب است. برای مثال این کلاس حاوی تعدادی خاصیت خواهد بود که از اطلاعات آنها در View مرتبط استفاده میشود. همچنین این کلاس میتواند حاوی متدهای مورد نیاز در View نیز باشد؛ برای مثال متدی که کار نمایش یا مخفی سازی یک تصویر را با کلیک بر روی دکمهای انجام میدهد.
- متادیتا: متادیتا (یا decorator در اینجا) به AngularJS 2.0 اعلام میکند که این کلاس تعریف شده، صرفا یک کلاس ساده نیست و باید به آن به صورت یک کامپوننت نگاه شود.
در ذیل، کدهای یک کامپوننت نمونهی AngularJS 2.0 را مشاهده میکنید:
در انتهای کدها، یک کلاس را مشاهده میکنید که کار تعریف خواص و متدهای مورد نیاز توسط View را انجام میدهد.
بلافاصله در بالای این کلاس، متد decorator ایی را به نام Component مشاهده میکنید. این متادیتا است که به AngularJS 2.0 اعلام میکند، کلاس AppComponent تعریف شده، یک کامپوننت است و نه تنها یک کلاس ساده.
در متد Component تعریف شده، قالب یا template نحوهی رندر این کامپوننت را مشاهده میکنید.
در ابتدای این ماژول نیز کار import تعاریف مرتبط با متد ویژهی Component، از هستهی AngularJS 2.0 انجام شدهاست تا کامپایلر TypeScript بتواند این فایل ts را کامپایل کند.
مروری بر نحوهی تعریف class در TypeScript
مرور جامع کلاسها در TypeScript را در مطلب «مبانی TypeScript؛ کلاسها» میتوانید مطالعه کنید. در اینجا جهت یادآوری، خلاصهای از آنرا که نیاز داریم، بررسی خواهیم کرد:
- جهت تعریف یک کلاس، ابتدا واژهی کلیدی class به همراه نام کلاس ذکر میشوند.
- در AngularJS 2.0 مرسوم است که نام کلاس را به صورت نام ویژگی مدنظر به همراه پسوند Component ذکر کنیم؛ مانند AppComponent مثال فوق. این نام pascal case است و با حروف بزرگ شروع میشود.
- همچنین مرسوم است در برنامههای AngularJS 2.0، کامپوننت ریشهی سایت نیز AppComponent نامیده شود.
- در مثال فوق، واژهی کلیدی export را نیز پیش از واژهی کلیدی class مشاهده میکنید. به این ترتیب این کلاس خارج از ماژولی که در آن تعریف میشود، قابل دسترسی خواهد بود. اکنون این کلاس و فایل، تبدیل به ماژولی خواهند شد که توسط module loader معرفی شدهی در ابتدای بحث یا همان System.JS به صورت خودکار بارگذاری میشود و دیگر نیازی به تعریف مدخل script متناظر با آن در فایل index.html نخواهد بود.
- در بدنهی کلاس، کار تعریف متدها و خواص مورد نیاز View صورت میگیرند. برای نمونه در اینجا تنها یک خاصیت «عنوان صفحه» تعریف شدهاست. در جاوا اسکریپت مرسوم است که نام خواص را camel case شروع شده با حروف کوچک تعریف کنیم. سپس نوع این خاصیت به صورت رشتهای تعریف شدهاست و در آخر مقدار پیش فرض این خاصیت ذکر گردیدهاست.
البته باید دقت داشت که الزامی به ذکر نوع خاصیت، در TypeScript وجود ندارد. همینقدر که مقدار پیش فرض این خاصیت رشتهای است، بر اساس ویژگی به نام Type inference در TypeScript، نوع این خاصیت نیز رشتهای درنظر گرفته خواهد شد و دیگر نمیتوان برای مثال یک عدد را به آن انتساب داد.
- سطح دسترسی خواص تعریف شدهی در یک کلاس TypeScript به صورت پیش فرض public است. بنابراین در اینجا نیازی به ذکر صریح آن نبودهاست.
مروری بر متادیتا یا decorator یک کلاس در AngularJS 2.0
خوب، تا اینجا کلاس AppComponent تعریف و همچنین export شد تا توسط system.js به صورت خودکار بارگذاری شود. اما این کلاس به خودی خود صرفا یک کلاس TypeScript ایی است و توسط AngularJS شناسایی نمیشود. برای معرفی این کلاس به صورت یک کامپوننت، از یک تزئین کننده یا decorator ویژه به نام Component استفاده میشود که بلافاصله در بالای تعریف کلاس قرار میگیرد؛ چیزی شبیه به data annotations یا attributes در زبان #C.
یک decorator متدی است که اطلاعاتی اضافی را به یک کلاس، اعضاء و متدهای آن و یا حتی آرگومانهای آن متدها، الصاق میکند. این ویژگی قرار است به صورت استاندارد در ES 2016 یا نگارش بعدی جاوا اسکریپت حضور داشته باشد و در حال حاضر توسط TypeScript پشتیبانی شده و در نهایت به کدهای ES 5 قابل اجرای در تمام مرورگرها ترجمه میشود.
یک decorator همیشه با @ شروع میشود و AngularJS 2.0 به همراه تعدادی decorator توکار است؛ مانند Component. از آنجائیکه decorator یک متد است، همیشه به همراه یک جفت پرانتز () ذکر میشود و در انتهای آن نیازی به ذکر سمیکالن نیست. در اینجا تزئین کنندهی Component یک شیء را میپذیر که به همراه تعدادی خاصیت است. به همین جهت پارامتر آن به صورت {} ذکر شدهاست.
خاصیت selector یک کامپوننت مشخص میکند که نام directive متناظر با این کامپوننت چیست:
از این نام، به صورت یک المان جدید و سفارشی HTML جهت تعریف این کامپوننت استفاده خواهیم کرد. برای مثال اگر به کدهای ابتدای بحث دقت کنید، نام pm-app به صورت ذیل و به شکل یک تگ جدید HTML استفاده شدهاست:
همچنین یک کامپوننت همواره به همراه یک قالب است که نحوهی رندر آنرا مشخص میکند:
در اینجا از back tick مربوط به ES 6.0 که توسط TypeScript نیز پشتیبانی میشود، جهت تعریف یک رشتهی چندسطری جاوا اسکریپتی، استفاده شدهاست.
همچنین {{}} به معنای تعریف data binding است. به این ترتیب مقداری که قرار است به صورت تگ h1 رندر شود، از خاصیت pageTitle کلاس مزین شدهی توسط این ویژگی یا decorator تامین خواهد شد؛ یعنی مقدار پیش فرض خاصیت pageTitle در کلاس AppComponent.
import اطلاعات مورد نیاز جهت کامپایل یک فایل TypeScript
تا اینجا مفاهیم موجود در کلاس AppComponent را به همراه متادیتای آن بررسی کردیم. اما این متادیتای جدید کامپوننت، به صورت پیش فرض ناشناختهاست:
همانطور که مشاهده میکنید، در اینجا ذیل کامپوننت، خط قرمزی جهت یادآوری عدم تعریف آن، کشیده شدهاست. در TypeScript و یا ES 6، پیش از استفاده از یک کلاس یا متد خارجی، نیاز است به module loader اعلام کنیم تا آنرا باید از کجا تامین کند. اینکار توسط عبارت import انجام میشود که شبیه به عبارت using در زبان سیشارپ است. عبارت import جزئی از استاندارد ES 6 است و همچنین در TypeScript نیز پشتیبانی میشود. به این ترتیب امکان دسترسی به ویژگیهای export شدهی از سایر ماژولها را در ماژول فعلی (فایل فعلی در حال کار) خواهیم یافت. نمونهی آنرا با ذکر واژهی کلیدی export پیش از کلاس AppComponent پیشتر ملاحظه کردید.
این ماژولهای خارجی میتوانند سایر ماژولها و فایلهای ts نوشته شدهی توسط خودمان و یا حتی اجزای AngularJS 2.0 باشند. طراحی AngularJS 2.0 نیز ماژولار است و از ماژولهایی مانند angular2/core، angular2/animation، angular2/http و angular2/router تشکیل شدهاست.
برای نمونه متادیتای کامپوننت، در ماژول angular2/core قرار دارد. به همین جهت نیاز است در ابتدای ماژول فعلی آنرا import کرد:
کار با ذکر واژهی کلیدی import شروع میشود. سپس جزئی را که نیاز داریم داخل {} ذکر کرده و در آخر مسیر یافتن آنرا مشخص میکنیم.
ساخت کامپوننت ریشهی یک برنامهی AngularJS 2.0
در ابتدای بحث که تعاریف مداخل مورد نیاز جهت اجرای یک برنامهی AngularJS 2.0 ذکر شدند، عنوان شد که system.js به دنبال ماژول آغازین app/main میگردد.
بنابراین در ریشهی پروژه، پوشهی جدیدی را به نام app ایجاد کنید.
سپس یک فایل TypeScript جدید را به نام app.component.ts به این پوشه اضافه کنید. قالب این نوع فایلها در add new item و با جستجو typescript در دسترس است و یا حتی یک فایل متنی ساده را هم با پسوند ts ایجاد کنید، کافی است.
نامگذاری این فایلها هم مرسوم است به صورت ذکر نام ویژگی به همراه یک دات و سپس ذکر کامپوننت صورت گیرد. در اینجا چون قصد داریم کامپوننت ریشهی برنامه را ایجاد کنیم، نام ویژگی آن app خواهد بود و نام کامل فایل به این ترتیب app.component.ts میشود.
سپس محتوای این فایل را به دقیقا معادل کدهای قسمت «نوشتن اولین کامپوننت AngularJS 2.0» ابتدای بحث تغییر دهید (همان import، متادیتا و کلاس AppComponent).
تا اینجا کامپوننت ریشهی برنامه ایجاد شد. اما چگونه باید از آن استفاده کنیم و چگونه AngularJS 2.0 آنرا شناسایی میکند؟ به این فرآیند آغازین شناسایی و بارگذاری ماژولها، اصطلاحا bootstrapping میگویند. تنها صفحهی واقعی موجود در یک برنامهی تک صفحهای وب، همان فایل index.html است و سایر صفحات و محتوای آنها به محتوای این صفحهی آغازین اضافه یا کم خواهند شد.
در اینجا برای نمایش اولین کامپوننت تهیه شده، نام تگ selector آن که توسط متادیتای کلاس AppComponent تعریف شد، در body فایل index.html به نحو فوق به صورت یک تگ سفارشی جدید اضافه میشود. به آن directive نیز میگویند.
خوب، اکنون module loader یا system.js چگونه این pm-app یا کامپوننت ریشهی برنامه را شناسایی میکند؟
این شناسایی توسط سطر System.import تعریف شدهی در فایل index.html انجام میشود. در اینجا system.js، در پوشهی app واقع در ریشهی سایت، به دنبال ماژول راه اندازی به نام main میگردد. یعنی نیاز است فایل TypeScript جدیدی را به نام main.ts به ریشهی پوشهی app اضافه کنیم. محتوای این فایل ویژهی بوت استرپ AngularJS 2.0 به صورت ذیل است:
این فایل ویژه را نیز مانند کلاس AppComponent که پیشتر بررسی کردیم، نیاز است از انتها به ابتدا بررسی کرد.
در انتهای این فایل متد bootstrap مربوط به AngularJS 2.0 را مشاهده میکنید. کار آن بارگذاری اولین ماژول و کامپوننت برنامه یا همان AppComponent است.
در ادامه نیاز است AppComponent را به این ماژول معرفی کرد؛ در غیراینصورت کامپایل نخواهد شد. برای این منظور سطر import این کلاس را از فایل app.component، مشاهده میکنید. در اینجا نیازی به ذکر پسوند ts. فایل app.component نیست.
سپس نیاز است محل تعریف متد بوت استرپ را نیز مشخص کنیم. این متد در ماژول angular2/platform/browser قرار دارد که به عنوان اولین import این فایل ذکر شدهاست.
سطر اول، مربوط است به تعریف فایلهای d.ts. مربوط به TypeScript جهت شناسایی نوعهای مرتبط با AngularJS 2.0. اگر اینکار صورت نگیرد، خطاهای ذیل را در حین کامپایل فایلهای TypeScript دریافت خواهید کرد:
تهیه فایل main.ts تنها یکبار صورت میگیرد و دیگر با آن کاری نخواهیم داشت.
تا اینجا پوشهی app واقع در ریشهی سایت، یک چنین شکلی را پیدا میکند:
و اکنون اگر برنامه را اجرا کنیم (فشردن دکمهی F5)، خروجی آن در مرورگر به صورت ذیل خواهد بود:
همچنین در اینجا میتوان HTML نهایی تزریق شدهی به صفحه را بهتر مشاهده کرد:
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: MVC5Angular2.part2.zip
برای اجرای آن، ابتدا به فایل project.json مراجعه کرده و یکبار آنرا ذخیره کنید تا وابستگیهای اسکریپتی پروژه از اینترنت دریافت شوند (این موارد در قسمت قبل مرور شدند). سپس یکبار هم پروژه را Build کنید تا تمام فایلهای ts آن کامپایل شوند و در آخر، اجرای نهایی پروژه.
خلاصهی بحث
یک برنامهی AngularJS 2.0 متشکل است از تعدادی کامپوننت. بنابراین کلاسی را ایجاد خواهیم کرد تا کدهای پشتیبانی کنندهی View این کامپوننت را تولید کند. سپس این کلاس را با متادیتایی مزین کرده و توسط آن تگ سفارشی ویژهی این کامپوننت و تگهای HTML تشکیل دهندهی این کامپوننت را به AngularJS 2.0 معرفی میکنیم. در اینجا در صورت نیاز وابستگیهای تعریف این متادیتا را توسط واژهی کلیدی import دریافت میکنیم. نام این کلاس بهتر است Pascal case بوده و با حروف بزرگ شروع شود و همچنین به صورت نام ویژگی ختم شدهی به کلمهی Component باشد. در اینجا حتما نیاز است این کلاس export شود تا توسط module loader قابل استفاده و بارگذاری گردد. اگر View این کامپوننت نیاز به دریافت اطلاعاتی دارد، این اطلاعات به صورت خواصی در کلاس کامپوننت تعریف میشوند. این خواص تعریف شدهی با سطح دسترسی عمومی، مرسوم است به صورت camel case تعریف شوند و حروف اول آنها کوچک باشد.
تعاریف مداخل فایل index.html یک سایت AngularJS 2.0
پروژهای که در اینجا در حال استفاده است یک برنامهی ASP.NET MVC 5.x است؛ اما الزامی هم به استفادهی از آن وجود ندارد. یا یک فایل index.html را به ریشهی پروژه اضافه کنید و یا فایل Views\Shared\_Layout.cshtml را به نحو ذیل تغییر دهید:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@ViewBag.Title - My ASP.NET Application</title> <link href="~/node_modules/bootstrap/dist/css/bootstrap.css" rel="stylesheet" /> <link href="~/app/app.component.css" rel="stylesheet"/> <link href="~/Content/Site.css" rel="stylesheet" type="text/css" /> <!-- 1. Load libraries --> <!-- IE required polyfills, in this exact order --> <script src="~/node_modules/angular2/es6/dev/src/testing/shims_for_IE.js"></script> <script src="~/node_modules/es6-shim/es6-shim.min.js"></script> <script src="~/node_modules/systemjs/dist/system-polyfills.js"></script> <script src="~/node_modules/angular2/bundles/angular2-polyfills.js"></script> <script src="~/node_modules/systemjs/dist/system.src.js"></script> <script src="~/node_modules/rxjs/bundles/Rx.js"></script> <script src="~/node_modules/angular2/bundles/angular2.dev.js"></script> <!-- Required for http --> <script src="~/node_modules/angular2/bundles/http.dev.js"></script> <!-- Required for routing --> <script src="~/node_modules/angular2/bundles/router.dev.js"></script> <!-- 2. Configure SystemJS --> <script> System.config({ packages: { app: { format: 'register', defaultExtension: 'js' } } }); System.import('app/main') .then(null, console.error.bind(console)); </script> </head> <body> <div> @RenderBody() <pm-app>Loading App...</pm-app> </div> @RenderSection("Scripts", required: false) </body> </html>
سپس کتابخانههای جاوا اسکریپتی مورد نیاز جهت کار با AngularJS 2.0 به ترتیبی که ذکر شده، باید تعریف شوند.
ذکر /~ در ابتدای آدرسها، مختص به ASP.NET MVC است. اگر از آن استفاده نمیکنید، نیازی به ذکر آن هم نیست.
در ادامه تعاریف System.JS ذکر شدهاست. System.JS کار بارگذاری ماژولهای برنامه را به عهده دارد. به این ترتیب دیگر نیازی نیست تا به ازای هر قسمت جدید برنامه، مدخلی را در اینجا اضافه کرد و کار بارگذاری آنها خودکار خواهد بود. فرمت register ایی که در اینجا ذکر شدهاست، تا ماژولهای استاندارد با فرمت ES 6 را نیز پشتیبانی میکند. همچنین با ذکر و تنظیم پسوند پیش فرض به js، دیگر نیازی نخواهد بود تا در حین تعریف importها در قسمتهای مختلف برنامه، پسوند فایلها را به صورت صریح ذکر کرد. مبحث improtها مرتبط است به مفاهیم ماژولها در ES 6 و همچنین TypeScript.
سطر System.import کار بارگذاری اولین ماژول برنامه را از پوشهی app قرار گرفته در ریشهی سایت انجام میدهد. این ماژول main نام دارد.
نوشتن اولین کامپوننت AngularJS 2.0
برنامههای AngularJS 2.0 متشکل هستند از تعدادی کامپوننت و سرویس:
و هر کامپوننت تشکیل شدهاست از:
- یک قالب یا Template: با استفاده از HTML تعریف میشود و کار تشکیل View و نحوهی رندر کامپوننت را مشخص میکند. در این Viewها با استفاده از امکانات binding و directives موجود در AngularJS 2.0 کار دسترسی به دادهها صورت میگیرد.
- یک کلاس: کار این کلاس که توسط TypeScript تهیه میشود، فراهم آوردن کدهای مرتبط با قالب است. برای مثال این کلاس حاوی تعدادی خاصیت خواهد بود که از اطلاعات آنها در View مرتبط استفاده میشود. همچنین این کلاس میتواند حاوی متدهای مورد نیاز در View نیز باشد؛ برای مثال متدی که کار نمایش یا مخفی سازی یک تصویر را با کلیک بر روی دکمهای انجام میدهد.
- متادیتا: متادیتا (یا decorator در اینجا) به AngularJS 2.0 اعلام میکند که این کلاس تعریف شده، صرفا یک کلاس ساده نیست و باید به آن به صورت یک کامپوننت نگاه شود.
در ذیل، کدهای یک کامپوننت نمونهی AngularJS 2.0 را مشاهده میکنید:
import { Component } from 'angular2/core'; @Component({ selector: 'pm-app', template:` <div><h1>{{pageTitle}}</h1> <div>My First Component</div> </div> ` }) export class AppComponent { pageTitle: string = "DNT AngularJS 2.0 APP"; }
بلافاصله در بالای این کلاس، متد decorator ایی را به نام Component مشاهده میکنید. این متادیتا است که به AngularJS 2.0 اعلام میکند، کلاس AppComponent تعریف شده، یک کامپوننت است و نه تنها یک کلاس ساده.
در متد Component تعریف شده، قالب یا template نحوهی رندر این کامپوننت را مشاهده میکنید.
در ابتدای این ماژول نیز کار import تعاریف مرتبط با متد ویژهی Component، از هستهی AngularJS 2.0 انجام شدهاست تا کامپایلر TypeScript بتواند این فایل ts را کامپایل کند.
مروری بر نحوهی تعریف class در TypeScript
مرور جامع کلاسها در TypeScript را در مطلب «مبانی TypeScript؛ کلاسها» میتوانید مطالعه کنید. در اینجا جهت یادآوری، خلاصهای از آنرا که نیاز داریم، بررسی خواهیم کرد:
- جهت تعریف یک کلاس، ابتدا واژهی کلیدی class به همراه نام کلاس ذکر میشوند.
- در AngularJS 2.0 مرسوم است که نام کلاس را به صورت نام ویژگی مدنظر به همراه پسوند Component ذکر کنیم؛ مانند AppComponent مثال فوق. این نام pascal case است و با حروف بزرگ شروع میشود.
- همچنین مرسوم است در برنامههای AngularJS 2.0، کامپوننت ریشهی سایت نیز AppComponent نامیده شود.
- در مثال فوق، واژهی کلیدی export را نیز پیش از واژهی کلیدی class مشاهده میکنید. به این ترتیب این کلاس خارج از ماژولی که در آن تعریف میشود، قابل دسترسی خواهد بود. اکنون این کلاس و فایل، تبدیل به ماژولی خواهند شد که توسط module loader معرفی شدهی در ابتدای بحث یا همان System.JS به صورت خودکار بارگذاری میشود و دیگر نیازی به تعریف مدخل script متناظر با آن در فایل index.html نخواهد بود.
- در بدنهی کلاس، کار تعریف متدها و خواص مورد نیاز View صورت میگیرند. برای نمونه در اینجا تنها یک خاصیت «عنوان صفحه» تعریف شدهاست. در جاوا اسکریپت مرسوم است که نام خواص را camel case شروع شده با حروف کوچک تعریف کنیم. سپس نوع این خاصیت به صورت رشتهای تعریف شدهاست و در آخر مقدار پیش فرض این خاصیت ذکر گردیدهاست.
البته باید دقت داشت که الزامی به ذکر نوع خاصیت، در TypeScript وجود ندارد. همینقدر که مقدار پیش فرض این خاصیت رشتهای است، بر اساس ویژگی به نام Type inference در TypeScript، نوع این خاصیت نیز رشتهای درنظر گرفته خواهد شد و دیگر نمیتوان برای مثال یک عدد را به آن انتساب داد.
- سطح دسترسی خواص تعریف شدهی در یک کلاس TypeScript به صورت پیش فرض public است. بنابراین در اینجا نیازی به ذکر صریح آن نبودهاست.
مروری بر متادیتا یا decorator یک کلاس در AngularJS 2.0
خوب، تا اینجا کلاس AppComponent تعریف و همچنین export شد تا توسط system.js به صورت خودکار بارگذاری شود. اما این کلاس به خودی خود صرفا یک کلاس TypeScript ایی است و توسط AngularJS شناسایی نمیشود. برای معرفی این کلاس به صورت یک کامپوننت، از یک تزئین کننده یا decorator ویژه به نام Component استفاده میشود که بلافاصله در بالای تعریف کلاس قرار میگیرد؛ چیزی شبیه به data annotations یا attributes در زبان #C.
یک decorator متدی است که اطلاعاتی اضافی را به یک کلاس، اعضاء و متدهای آن و یا حتی آرگومانهای آن متدها، الصاق میکند. این ویژگی قرار است به صورت استاندارد در ES 2016 یا نگارش بعدی جاوا اسکریپت حضور داشته باشد و در حال حاضر توسط TypeScript پشتیبانی شده و در نهایت به کدهای ES 5 قابل اجرای در تمام مرورگرها ترجمه میشود.
یک decorator همیشه با @ شروع میشود و AngularJS 2.0 به همراه تعدادی decorator توکار است؛ مانند Component. از آنجائیکه decorator یک متد است، همیشه به همراه یک جفت پرانتز () ذکر میشود و در انتهای آن نیازی به ذکر سمیکالن نیست. در اینجا تزئین کنندهی Component یک شیء را میپذیر که به همراه تعدادی خاصیت است. به همین جهت پارامتر آن به صورت {} ذکر شدهاست.
خاصیت selector یک کامپوننت مشخص میکند که نام directive متناظر با این کامپوننت چیست:
selector: 'pm-app',
<div> @RenderBody() <pm-app>Loading App...</pm-app> </div>
template:` <div><h1>{{pageTitle}}</h1> <div>My First Component</div> </div> `
همچنین {{}} به معنای تعریف data binding است. به این ترتیب مقداری که قرار است به صورت تگ h1 رندر شود، از خاصیت pageTitle کلاس مزین شدهی توسط این ویژگی یا decorator تامین خواهد شد؛ یعنی مقدار پیش فرض خاصیت pageTitle در کلاس AppComponent.
import اطلاعات مورد نیاز جهت کامپایل یک فایل TypeScript
تا اینجا مفاهیم موجود در کلاس AppComponent را به همراه متادیتای آن بررسی کردیم. اما این متادیتای جدید کامپوننت، به صورت پیش فرض ناشناختهاست:
همانطور که مشاهده میکنید، در اینجا ذیل کامپوننت، خط قرمزی جهت یادآوری عدم تعریف آن، کشیده شدهاست. در TypeScript و یا ES 6، پیش از استفاده از یک کلاس یا متد خارجی، نیاز است به module loader اعلام کنیم تا آنرا باید از کجا تامین کند. اینکار توسط عبارت import انجام میشود که شبیه به عبارت using در زبان سیشارپ است. عبارت import جزئی از استاندارد ES 6 است و همچنین در TypeScript نیز پشتیبانی میشود. به این ترتیب امکان دسترسی به ویژگیهای export شدهی از سایر ماژولها را در ماژول فعلی (فایل فعلی در حال کار) خواهیم یافت. نمونهی آنرا با ذکر واژهی کلیدی export پیش از کلاس AppComponent پیشتر ملاحظه کردید.
این ماژولهای خارجی میتوانند سایر ماژولها و فایلهای ts نوشته شدهی توسط خودمان و یا حتی اجزای AngularJS 2.0 باشند. طراحی AngularJS 2.0 نیز ماژولار است و از ماژولهایی مانند angular2/core، angular2/animation، angular2/http و angular2/router تشکیل شدهاست.
برای نمونه متادیتای کامپوننت، در ماژول angular2/core قرار دارد. به همین جهت نیاز است در ابتدای ماژول فعلی آنرا import کرد:
import { Component } from 'angular2/core';
ساخت کامپوننت ریشهی یک برنامهی AngularJS 2.0
در ابتدای بحث که تعاریف مداخل مورد نیاز جهت اجرای یک برنامهی AngularJS 2.0 ذکر شدند، عنوان شد که system.js به دنبال ماژول آغازین app/main میگردد.
بنابراین در ریشهی پروژه، پوشهی جدیدی را به نام app ایجاد کنید.
سپس یک فایل TypeScript جدید را به نام app.component.ts به این پوشه اضافه کنید. قالب این نوع فایلها در add new item و با جستجو typescript در دسترس است و یا حتی یک فایل متنی ساده را هم با پسوند ts ایجاد کنید، کافی است.
نامگذاری این فایلها هم مرسوم است به صورت ذکر نام ویژگی به همراه یک دات و سپس ذکر کامپوننت صورت گیرد. در اینجا چون قصد داریم کامپوننت ریشهی برنامه را ایجاد کنیم، نام ویژگی آن app خواهد بود و نام کامل فایل به این ترتیب app.component.ts میشود.
سپس محتوای این فایل را به دقیقا معادل کدهای قسمت «نوشتن اولین کامپوننت AngularJS 2.0» ابتدای بحث تغییر دهید (همان import، متادیتا و کلاس AppComponent).
تا اینجا کامپوننت ریشهی برنامه ایجاد شد. اما چگونه باید از آن استفاده کنیم و چگونه AngularJS 2.0 آنرا شناسایی میکند؟ به این فرآیند آغازین شناسایی و بارگذاری ماژولها، اصطلاحا bootstrapping میگویند. تنها صفحهی واقعی موجود در یک برنامهی تک صفحهای وب، همان فایل index.html است و سایر صفحات و محتوای آنها به محتوای این صفحهی آغازین اضافه یا کم خواهند شد.
<div> @RenderBody() <pm-app>Loading App...</pm-app> </div>
خوب، اکنون module loader یا system.js چگونه این pm-app یا کامپوننت ریشهی برنامه را شناسایی میکند؟
System.import('app/main')
/// <reference path="../node_modules/angular2/typings/browser.d.ts" /> import { bootstrap } from "angular2/platform/browser"; // Our main component import { AppComponent } from "./app.component"; bootstrap(AppComponent);
در انتهای این فایل متد bootstrap مربوط به AngularJS 2.0 را مشاهده میکنید. کار آن بارگذاری اولین ماژول و کامپوننت برنامه یا همان AppComponent است.
در ادامه نیاز است AppComponent را به این ماژول معرفی کرد؛ در غیراینصورت کامپایل نخواهد شد. برای این منظور سطر import این کلاس را از فایل app.component، مشاهده میکنید. در اینجا نیازی به ذکر پسوند ts. فایل app.component نیست.
سپس نیاز است محل تعریف متد بوت استرپ را نیز مشخص کنیم. این متد در ماژول angular2/platform/browser قرار دارد که به عنوان اولین import این فایل ذکر شدهاست.
سطر اول، مربوط است به تعریف فایلهای d.ts. مربوط به TypeScript جهت شناسایی نوعهای مرتبط با AngularJS 2.0. اگر اینکار صورت نگیرد، خطاهای ذیل را در حین کامپایل فایلهای TypeScript دریافت خواهید کرد:
node_modules\angular2\src\core\application_ref.d.ts(171,81): error TS2304: Build: Cannot find name 'Promise'. node_modules\angular2\src\core\change_detection\differs\default_keyvalue_differ.d.ts(23,15): error TS2304: Build: Cannot find name 'Map'.
تا اینجا پوشهی app واقع در ریشهی سایت، یک چنین شکلی را پیدا میکند:
و اکنون اگر برنامه را اجرا کنیم (فشردن دکمهی F5)، خروجی آن در مرورگر به صورت ذیل خواهد بود:
با توجه به اینکه در حال کار با یک برنامهی جاوا اسکریپتی هستیم، باز نگه داشتن developer tools مرورگر، جهت مشاهدهی خطاهای احتمالی ضروری است.
در اینجا اگر خطایی وجود داشته باشد، یا اطلاعات اضافی مدنظر باشد، در console لاگ خواهند شد. برای مثال در اینجا عنوان شدهاست که برنامه در حالت توسعه در حال اجرا است. بهتر است برای ارائهی نهایی، متد enableProdMode را در فایل index.html فراخوانی کنید.
همچنین در اینجا میتوان HTML نهایی تزریق شدهی به صفحه را بهتر مشاهده کرد:
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: MVC5Angular2.part2.zip
برای اجرای آن، ابتدا به فایل project.json مراجعه کرده و یکبار آنرا ذخیره کنید تا وابستگیهای اسکریپتی پروژه از اینترنت دریافت شوند (این موارد در قسمت قبل مرور شدند). سپس یکبار هم پروژه را Build کنید تا تمام فایلهای ts آن کامپایل شوند و در آخر، اجرای نهایی پروژه.
خلاصهی بحث
یک برنامهی AngularJS 2.0 متشکل است از تعدادی کامپوننت. بنابراین کلاسی را ایجاد خواهیم کرد تا کدهای پشتیبانی کنندهی View این کامپوننت را تولید کند. سپس این کلاس را با متادیتایی مزین کرده و توسط آن تگ سفارشی ویژهی این کامپوننت و تگهای HTML تشکیل دهندهی این کامپوننت را به AngularJS 2.0 معرفی میکنیم. در اینجا در صورت نیاز وابستگیهای تعریف این متادیتا را توسط واژهی کلیدی import دریافت میکنیم. نام این کلاس بهتر است Pascal case بوده و با حروف بزرگ شروع شود و همچنین به صورت نام ویژگی ختم شدهی به کلمهی Component باشد. در اینجا حتما نیاز است این کلاس export شود تا توسط module loader قابل استفاده و بارگذاری گردد. اگر View این کامپوننت نیاز به دریافت اطلاعاتی دارد، این اطلاعات به صورت خواصی در کلاس کامپوننت تعریف میشوند. این خواص تعریف شدهی با سطح دسترسی عمومی، مرسوم است به صورت camel case تعریف شوند و حروف اول آنها کوچک باشد.
اشتراکها
عدم پشتیبانی W2G از ویژوال استودیو
قابلیت Windwos to Go که در ویندوز 8 نسخه Enterprise وجود دارد توانایی هایی جالبی را ارائه میکند که شما میتوانید ویندوز 8 را به صورت همراه در یک فلش نصب کنید. اما متاسفانه اگر فلش شما از نوع فلشهای تایید شده توسط مایکروسافت نباشه نمیتوان ویژوال استودیو و MS-SQL Server را روی آن نصب کرد.
پیشنهاد: بنده به این نکته دقت نکردم و حالا دنبال راه حلی برای نصب ویژوال استودیو برروی فلش خود هستم که احتمالا به پرتابل کردن آن دست بزنم، لذا پیشنهاد میکنم هرکسی بخواهد این کار را انجام دهد حتما فلش خود را از بین لیست فلشهای تایید شده مایکروسافت انتخاب کند(این لیست را در لینک مرجع که در لینک این پست قرار دارد میتوان یافت).
موفق باشید.
- مطلب آن فرد هندی که لینک دادید، به نظر از این مطلب استفاده کرده.
- برای دسترسی به اکشن متدهای محافظت شدهی با ویژگی خالی Authorize (بدون هیچگونه تنظیم دیگری)، تنها وجود شرط ورود به سیستم کافی است. اگر Policy یا Role خاصی بر روی آنها اعمال شود، آنگاه آن شخص باید User Claims ویژهای را داشته باشد تا بتواند شرایط آن Policy را تامین کند. در مورد نوشتن انواع و اقسام Policyهای سفارشی (چه بر اساس شرایط User Claims ثابت (policy => policy.RequireClaim) و چه پویا که به همراه AuthorizationHandlerها هستند) در این مطلب بحث شده و شما محدود به تنظیمات پیشفرض پروژه نیستید.
- مطلب «تنظیمات کش توزیع شدهی مبتنی بر SQL Server در ASP.NET Core» و خصوصا نظرات آنرا مطالعه کنید.
استفادهی گستردهی از jQuery به همراه برنامههای AngularJS 2.0 ایدهی خوبی نیست؛ زیرا jQuery و کدهای آن، ارتباط تنگاتنگی را بین DOM و JavaScript برقرار میکنند که برخلاف رویهی فریمورکهای MVC است. اما با این حال استفادهی از افزونههای بیشمار jQuery در برنامههای AngularJS 2.0، جهت غنا بخشیدن به ظاهر و همچنین کاربردپذیری برنامه، یکی از استفادههای پذیرفته شدهی آن است.
روش استفادهی از jQuery نیز در حالت کلی همانند مطلب «استفاده از کتابخانههای ثالث جاوا اسکریپتی در برنامههای AngularJS 2.0» است؛ اما به همراه چند نکتهی اضافهتر مانند محل فراخوانی و دسترسی به DOM، در کدهای یک کامپوننت.
هدف: استفاده از کتابخانهی Chosen
میخواهیم جهت غنیتر کردن ظاهر یک دراپ داون در برنامههای AngularJS 2.0، از یک افزونهی بسیار معروف jQuery به نام Chosen استفاده کنیم.
تامین پیشنیازهای اولیه
میتوان فایلهای این کتابخانه را مستقیما از GitHub دریافت و به پروژه اضافه کرد. اما بهتر است اینکار را توسط bower مدیریت کنیم. این کتابخانه هنوز دارای بستهی رسمی npm نیست (و بستهی chosen-npm که در مخزن npm وجود دارد، توسط این تیم ایجاد نشدهاست). اما همانطور که در مستندات آن نیز آمدهاست، توسط دستور ذیل نصب میشود:
برای مدیریت این مساله در ویژوال استودیو، به منوی project و گزینهی add new item مراجعه کرده و bower را جستجو کنید:
در اینجا نام پیش فرض bower.json را پذیرفته و سپس محتوای فایل ایجاد شده را به نحو ذیل تغییر دهید:
ساختار این فایل هم بسیار شبیهاست به ساختار package.json مربوط به npm. در اینجا کتابخانهی chosen در قسمت لیست وابستگیها اضافه شدهاست. با ذخیره کردن این فایل، کار دریافت خودکار بستههای تعریف شده، آغاز میشود و یا کلیک راست بر روی فایل bower.json دارای گزینهی restore packages نیز هست.
پس از دریافت خودکار chosen، بستهی آنرا در مسیر bower_components\chosen واقع در ریشهی پروژه میتوانید مشاهده کنید.
استفاده از jQuery و chosen به صورت untyped
سادهترین و متداولترین روش استفاده از jQuery و افزونههای آن شامل موارد زیر هستند:
الف) تعریف مداخل مرتبط با آنها در فایل index.html
که در اینجا jQuery و بوت استرپ و chosen به همراه فایل css آن اضافه شدهاند.
ب) تعریف jQuery به صورت untyped
همینقدر که این یک سطر را به ابتدای ماژول خود اضافه کنید، امکان دسترسی به تمام امکانات جیکوئری را خواهید یافت. البته بدون intellisense و بررسی نوعهای پارامترها؛ چون نوع آن، any یا همان حالت پیش فرض جاوا اسکریپت تعریف شدهاست.
محل صحیح فراخوانی متدهای مرتبط با jQuery
در تصویر ذیل، چرخهی حیات یک کامپوننت را مشاهده میکنید که با تعدادی از آنها پیشتر آشنا شدهایم:
همچنین جیکوئری نیاز دارد تا بداند هم اکنون قرار است با چه المانی کار کنیم و کامپوننت بارگذاری شده کدام است. برای این منظور، یکی از سرویسهای توکار AngularJS 2.0 را به نام ElementRef، به سازندهی کلاس تزریق میکنیم. توسط خاصیت this._el.nativeElement آن میتوان به المان ریشهی کامپوننت جاری دسترسی یافت.
تهیهی کامپوننت نمایش یک دراپ داون مزین شده با chosen
در ادامه قصد داریم نکاتی را که تاکنون مرور کردیم، به صورت یک مثال پیاده سازی کنیم. به همین جهت فایل جدید using-jquery-addons.component.ts را به پروژه اضافه کنید به همراه فایل قالب آن به نام using-jquery-addons.component.html؛ با این محتوا:
الف) کامپوننت using-jquery-addons.component.ts
ب) قالب using-jquery-addons.component.html
با این خروجی
توضیحات
کلاس UsingJQueryAddonsComponent، اینترفیس AfterViewInit را پیاده سازی کردهاست؛ تا توسط متد ngAfterViewInit بتوانیم با عناصر DOM کار کنیم. هرچند در کل اینکار باید صرفا محدود شود به مواردی مانند مثال جاری و در حد آغاز یک افزونهی jQuery و اگر قرار است تغییراتی دیگری صورت گیرند بهتر است از همان روش binding توکار AngularJS 2.0 استفاده کرد.
در سازندهی کلاس، سرویس ElementRef تزریق شدهاست تا توسط خاصیت this._el.nativeElement آن بتوان به المان ریشهی کامپوننت جاری دسترسی یافت. به همین جهت است که پس از آن از متد find، برای یافتن دراپ داون استفاده شدهاست و سپس chosen به نحو متداولی به آن اعمال گردیدهاست.
در اینجا هر زمانیکه یکی از آیتمهای دراپ داون انتخاب شوند، مقدار آن به خاصیت selectedValue انتساب داده شده و این انتساب سبب فعال سازی binding و نمایش مقدار آن در ذیل دراپ داون میگردد.
در قالب این کامپوننت هم با استفاده از ngFor، عناصر دراپ داون از آرایهی dropDownItems تعریف شده در کلاس کامپوننت، تامین میشوند. متغیر محلی item تعریف شدهی در اینجا، در محدودی همین المان قابل دسترسی است. برای مثال از آن جهت تنظیم دومین آیتم لیست به صورت انتخاب شده، در حین اولین بار نمایش view استفاده شدهاست.
استفاده از jQuery و chosen به صورت typed
کتابخانهی jQuery در مخزن کد https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/jquery دارای فایل d.ts. خاص خود است. برای نصب آن میتوان از روش ذیل استفاده کرد:
پس از افزودن فایل typings این کتابخانه، در ابتدای فایل main.ts یک سطر ذیل را اضافه کنید:
اینکار سبب خواهد شد تا intellisense درون ویژوال استودیو بتواند مداخل متناظر را یافته و راهنمای مناسبی را ارائه دهد.
در ادامه به فایل using-jquery-addons.component.ts مراجعه کرده و تغییر ذیل را اعمال کنید:
فایل d.ts. اضافه شده، امکان استفادهی از نوع جدید JQueryStatic را مهیا میکند. پس از آن در کدهای تعریف شده، chosen به رنگ قرمز در میآید، چون در تعاریف نوع دار jQuery، این افزونه وجود خارجی ندارد. برای رفع این مشکل، فایل typings/browser/ambient/jquery/index.d.ts را گشوده و سپس به انتهای آن، تعریف chosen را به صورت دستی اضافه کنید:
به این ترتیب این متد به عنوان جزئی از متدهای زنجیروار jQuery، شناسایی شده و قابل استفاده خواهد شد.
کدهای کامل این پروژه را از اینجا میتوانید دریافت کنید.
روش استفادهی از jQuery نیز در حالت کلی همانند مطلب «استفاده از کتابخانههای ثالث جاوا اسکریپتی در برنامههای AngularJS 2.0» است؛ اما به همراه چند نکتهی اضافهتر مانند محل فراخوانی و دسترسی به DOM، در کدهای یک کامپوننت.
هدف: استفاده از کتابخانهی Chosen
میخواهیم جهت غنیتر کردن ظاهر یک دراپ داون در برنامههای AngularJS 2.0، از یک افزونهی بسیار معروف jQuery به نام Chosen استفاده کنیم.
تامین پیشنیازهای اولیه
میتوان فایلهای این کتابخانه را مستقیما از GitHub دریافت و به پروژه اضافه کرد. اما بهتر است اینکار را توسط bower مدیریت کنیم. این کتابخانه هنوز دارای بستهی رسمی npm نیست (و بستهی chosen-npm که در مخزن npm وجود دارد، توسط این تیم ایجاد نشدهاست). اما همانطور که در مستندات آن نیز آمدهاست، توسط دستور ذیل نصب میشود:
bower install chosen
در اینجا نام پیش فرض bower.json را پذیرفته و سپس محتوای فایل ایجاد شده را به نحو ذیل تغییر دهید:
{ "name": "asp-net-mvc5x-angular2x", "version": "1.0.0", "authors": [ "DNT" ], "license": "MIT", "ignore": [ "node_modules", "bower_components" ], "dependencies": { "chosen": "1.4.2" }, "devDependencies": { } }
پس از دریافت خودکار chosen، بستهی آنرا در مسیر bower_components\chosen واقع در ریشهی پروژه میتوانید مشاهده کنید.
استفاده از jQuery و chosen به صورت untyped
سادهترین و متداولترین روش استفاده از jQuery و افزونههای آن شامل موارد زیر هستند:
الف) تعریف مداخل مرتبط با آنها در فایل index.html
<script src="~/node_modules/jquery/dist/jquery.min.js"></script> <script src="~/node_modules/bootstrap/dist/js/bootstrap.min.js"></script> <script src="~/bower_components/chosen/chosen.jquery.min.js"></script> <link href="~/bower_components/chosen/chosen.min.css" rel="stylesheet" type="text/css" />
ب) تعریف jQuery به صورت untyped
declare var jQuery: any;
محل صحیح فراخوانی متدهای مرتبط با jQuery
در تصویر ذیل، چرخهی حیات یک کامپوننت را مشاهده میکنید که با تعدادی از آنها پیشتر آشنا شدهایم:
روش متداول استفاده از jQuery، فراخوانی آن پس از رخداد document ready است. در اینجا معادل این رخداد، hook ویژهای به نام ngAfterViewInit است. بنابراین تمام فراخوانیهای jQuery را باید در این متد انجام داد.
همچنین جیکوئری نیاز دارد تا بداند هم اکنون قرار است با چه المانی کار کنیم و کامپوننت بارگذاری شده کدام است. برای این منظور، یکی از سرویسهای توکار AngularJS 2.0 را به نام ElementRef، به سازندهی کلاس تزریق میکنیم. توسط خاصیت this._el.nativeElement آن میتوان به المان ریشهی کامپوننت جاری دسترسی یافت.
constructor(private _el: ElementRef) { }
تهیهی کامپوننت نمایش یک دراپ داون مزین شده با chosen
در ادامه قصد داریم نکاتی را که تاکنون مرور کردیم، به صورت یک مثال پیاده سازی کنیم. به همین جهت فایل جدید using-jquery-addons.component.ts را به پروژه اضافه کنید به همراه فایل قالب آن به نام using-jquery-addons.component.html؛ با این محتوا:
الف) کامپوننت using-jquery-addons.component.ts
import { Component, ElementRef, AfterViewInit } from "@angular/core"; declare var jQuery: any; // untyped @Component({ templateUrl: "app/using-jquery-addons/using-jquery-addons.component.html" }) export class UsingJQueryAddonsComponent implements AfterViewInit { dropDownItems = ["First", "Second", "Third"]; selectedValue = "Second"; constructor(private _el: ElementRef) { } ngAfterViewInit() { jQuery(this._el.nativeElement) .find("select") .chosen() .on("change", (e, args) => { this.selectedValue = args.selected; }); } }
ب) قالب using-jquery-addons.component.html
<select> <option *ngFor="let item of dropDownItems" [value]="item" [selected]="item == selectedValue"> {{item}} option </option> </select> <h4> {{selectedValue}}</h4>
توضیحات
کلاس UsingJQueryAddonsComponent، اینترفیس AfterViewInit را پیاده سازی کردهاست؛ تا توسط متد ngAfterViewInit بتوانیم با عناصر DOM کار کنیم. هرچند در کل اینکار باید صرفا محدود شود به مواردی مانند مثال جاری و در حد آغاز یک افزونهی jQuery و اگر قرار است تغییراتی دیگری صورت گیرند بهتر است از همان روش binding توکار AngularJS 2.0 استفاده کرد.
در سازندهی کلاس، سرویس ElementRef تزریق شدهاست تا توسط خاصیت this._el.nativeElement آن بتوان به المان ریشهی کامپوننت جاری دسترسی یافت. به همین جهت است که پس از آن از متد find، برای یافتن دراپ داون استفاده شدهاست و سپس chosen به نحو متداولی به آن اعمال گردیدهاست.
در اینجا هر زمانیکه یکی از آیتمهای دراپ داون انتخاب شوند، مقدار آن به خاصیت selectedValue انتساب داده شده و این انتساب سبب فعال سازی binding و نمایش مقدار آن در ذیل دراپ داون میگردد.
در قالب این کامپوننت هم با استفاده از ngFor، عناصر دراپ داون از آرایهی dropDownItems تعریف شده در کلاس کامپوننت، تامین میشوند. متغیر محلی item تعریف شدهی در اینجا، در محدودی همین المان قابل دسترسی است. برای مثال از آن جهت تنظیم دومین آیتم لیست به صورت انتخاب شده، در حین اولین بار نمایش view استفاده شدهاست.
استفاده از jQuery و chosen به صورت typed
کتابخانهی jQuery در مخزن کد https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/jquery دارای فایل d.ts. خاص خود است. برای نصب آن میتوان از روش ذیل استفاده کرد:
npm install -g typings typings install jquery --save --ambient
/// <reference path="../typings/browser/ambient/jquery/index.d.ts" />
در ادامه به فایل using-jquery-addons.component.ts مراجعه کرده و تغییر ذیل را اعمال کنید:
// declare var jQuery: any; // untyped declare var jQuery: JQueryStatic; // typed
interface JQuery { //... chosen(options?:any):JQuery; } declare module "jquery" { export = $; }
کدهای کامل این پروژه را از اینجا میتوانید دریافت کنید.