برای VS 2013 این اصلاح را هم که مرتبط با AngularJS 2.0 هست، نصب کنید (پس از نصب پلاگین آن). این اصلاحیهی ویژه برای VS 2015 درصورتیکه TypeScript 2.0.3 را نصب کرده باشید، نیازی نیست.
AngularJS #2
Install-Package angularjs
<!DOCTYPE html> <html ng-app> <head> <title>Sample 1</title> </head> <body> <div ng-controller="GreetingController"> <p>{{greeting.text}}, World!</p> </div> <script src="../Scripts/angular.js"></script> <script> function GreetingController($scope) { $scope.greeting = { text: "Hello" }; } </script> </body> </html>
کتاب Bing Maps V8 Succinctly
At least 80% of all information being collected by enterprises includes geolocation data. The Bing Maps V8 library is a very large collection of JavaScript code that allows web developers to place a map on a webpage, query for data, and manipulate objects on a map, creating a geo-application. In Bing Maps V8 Succinctly, James McCaffrey takes readers through utilizing this library, from creating the simplest application that uses it, to mastering more advanced functions like creating color-gradient legends and custom-styled Infobox objects.
- Getting Started
- Fundamental Techniques
- Working with Data
- Advanced Techniques
در نسخههای قبل از Angular CLI 6.0، صرفا امکان Bundle کردن جداگانهی ماژولهایی که در قسمت loadChildren مرتبط با تنظیمات مسیریابی ذکر شده بودند، وجود داشت. بنابراین در برخی از شرایط اگر نیاز به امکان بارگذاری ماژولی به صورت Lazy load بود، باید از سیستم مسیریابی استفاده میشد یا اینکه با یکسری ترفند، CLI و Webpack را مجبور به ساخت فایل chunk جداگانه برای ماژول مورد نظر میکردید. از زمان انتشار Angular CLI 6.0 امکان Lazy loading پویا نیز مهیا میباشد؛ به این ترتیب بدون وابستگی به سیستم مسیریابی، باز هم میتوان از مزایای Lazy loading بهره برد. در این مطلب روش استفاده از این قابلیت و همچنین نحوهی بارگذاری پویای یک کامپوننت مرتبط با یک ماژول Lazy load شده را بررسی خواهیم کرد. برای این منظور در ادامه با ایجاد یک TabLayout با استفاده از Angular Material Tabs با یکی از موارد پر استفادهی قابلیت مذکور آشنا خواهیم شد.
پیش نیازها
- مسیر آموزشی «+AngularJS 2.0»
- مسیر آموزشی «سری آموزشی Angular CLI»
- مسیر آموزشی «مسیریابی در Angular»
- مسیر آموزشی «کتابخانه Angular Material 6x»
کار را با طراحی و پیاده سازی TabService شروع میکنیم. برای این منظور یک سرویس را در فولدر services موجود در کنار CoreModule ایجاد خواهیم کرد؛ به این جهت ابتدا مدلهای زیر را خواهیم داشت:
import { Type, ValueProvider } from '@angular/core'; export interface OpenNewTabModel { label: string; componentType: Type<any>; iconName: string; modulePath?: string; data?: ValueProvider[]; }
import { TabItemComponent } from './tab-item-component'; export interface TabItem { label: string; iconName: string; component: TabItemComponent; }
OpenNewTabModel برای ارسال داده توسط مصرف کننده از این سرویس در نظر گرفته شده است. ولی واسط TabItem دارای خصوصیاتی میباشد که ما برای نمایش یک برگهی جدید نیازمندیم. TabItemComponent نیز دارای خصوصیاتی است که مورد نیاز دایرکتیو« NgComponentOutlet» است.
import { Injector, NgModuleFactory, Type } from '@angular/core'; export interface TabItemComponent { componentType: Type<any>; moduleFactory?: NgModuleFactory<any>; injector: Injector; }
import { BehaviorSubject, Observable } from 'rxjs'; import { Injectable, Injector, NgModuleFactory, NgModuleFactoryLoader } from '@angular/core'; import { OpenNewTabModel } from '../models/open-new-tab-model'; import { TabItem } from '../models/tab-item'; @Injectable({ providedIn: 'root' }) export class TabService { private tabItemSubject: BehaviorSubject<TabItem[]> = new BehaviorSubject< TabItem[] >([]); constructor( private loader: NgModuleFactoryLoader, private injector: Injector ) {} get tabItems$(): Observable<TabItem[]> { return this.tabItemSubject.asObservable(); } open(newTab: OpenNewTabModel) { if (newTab.modulePath) { this.loader .load(newTab.modulePath) .then((moduleFactory: NgModuleFactory<any>) => { this.openInternal(newTab, moduleFactory); }); } else { this.openInternal(newTab); } } private openInternal(newTab: OpenNewTabModel, moduleFactory?: NgModuleFactory<any>) { const newTabItem: TabItem = { label: newTab.label, iconName: newTab.iconName, component: { componentType: newTab.componentType, moduleFactory: moduleFactory, injector: newTab.data ? Injector.create(newTab.data, this.injector) : this.injector } }; this.tabItemSubject.getValue().push(newTabItem); this.tabItemSubject.next(this.tabItemSubject.getValue()); } close(index: number) { this.tabItemSubject.getValue().splice(index, 1); this.tabItemSubject.next(this.tabItemSubject.getValue()); } }
{ provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader }
import { Component, OnInit } from '@angular/core'; import { TabService } from './../../../services/tab.service'; @Component({ selector: 'app-tabs', templateUrl: './tabs.component.html', styleUrls: ['./tabs.component.scss'] }) export class TabsComponent implements OnInit { constructor(public service: TabService) {} ngOnInit() {} }
<mat-tab-group> <mat-tab *ngFor="let tabItem of (service.tabItems$ | async); let index = index" > <ng-template mat-tab-label> <mat-icon class="icon" aria-label="icon for tab" >{{tabItem.iconName}}</mat-icon> <span class="full">{{ tabItem.label }}</span> <mat-icon class="close" (click)="service.close(index)" aria-label="close tab button" >close</mat-icon > <!-- </button> --> </ng-template> <ng-container *ngIf="tabItem.component.moduleFactory"> <ng-container *ngComponentOutlet=" tabItem.component.componentType; ngModuleFactory: tabItem.component.moduleFactory; injector: tabItem.component.injector " > </ng-container> </ng-container> <ng-container *ngIf="!tabItem.component.moduleFactory"> <ng-container *ngComponentOutlet=" tabItem.component.componentType; injector: tabItem.component.injector " > </ng-container> </ng-container> </mat-tab> </mat-tab-group>
در تکه کد بالا، ابتدا با استفاده از وهله تزریق شده TabService در کامپوننت مذکور، به شکل زیر، مشترک تغییرات لیست برگهها شدهایم و با استفاده از دایرکتیو *ngFor به ازای تک تک tabItemهای درخواست شده برای گشوده شدن، به شکل زیر کار وهله سازی پویا از کامپوننت مشخص شده انجام میشود:
<ng-container *ngComponentOutlet="tabItem.component.componentType; ngModuleFactory: tabItem.component.moduleFactory; injector: tabItem.component.injector"> </ng-container>
خوب، با استفاده از آنچه تا اینجای مطلب بررسی شد، میتوان یک سیستم راهبری مبتنی بر Tab را نیز برپا کرد که مطلب جدایی را میطلبد. برای تکمیل مکانیزم بارگذاری پویای ماژولها، نیاز است تا مسیر ماژول مورد نظر را در فایل angular.json و بخش lazyModules به شکل زیر معرفی کنید:
"build": { "builder": "@angular-devkit/build-angular:browser", "options": { "outputPath": "dist/MaterialAngularTabLayout", "index": "src/index.html", "main": "src/main.ts", "polyfills": "src/polyfills.ts", "tsConfig": "src/tsconfig.app.json", "assets": [ "src/favicon.ico", "src/assets" ], "styles": [ "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "src/styles.scss" ], "lazyModules": [ "src/app/lazy/lazy.module" ], "scripts": [] },
به عنوان مثال قصد داریم ماژول LazyModule را به صورت پویا بارگذاری کرده و LazyComponent موجود در این ماژول را به صورت پویا در برگهی جدیدی نمایش دهیم. برای این منظور کدهای فایل AppComponent.ts را به شکل زیر تغییر خواهیم داد:
import { Component } from '@angular/core'; import { IdModel } from './core/models/id-model'; import { LazyComponent } from './lazy/lazy.component'; import { OpenNewTabModel } from './core/models/open-new-tab-model'; import { TabService } from './core/services/tab.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'MaterialAngularTabLayout'; constructor(private tabService: TabService) {} loadLazyComponent() { this.tabService.open(<OpenNewTabModel>{ label: 'Loaded Lazy Component', iconName: 'thumb_up', componentType: LazyComponent, modulePath: 'src/app/lazy/lazy.module#LazyModule', data: [{ provide: IdModel, useValue: <IdModel>{ id: 1 } }] }); } }
در تکه کد بالا با تزریق TabService به سازندهی آن، قصد گشودن برگهی جدیدی را توسط متد open آن، داریم. در بدنهی متد loadLazyComponent یک شیء با قرارداد OpenNewTabModel ایجاد شده و به عنوان آرگومان به متد open ارسال شده است. توجه داشته باشید که modulePath اینجا نیز به مانند خصوصیت loadChildren مرتبط با اشیاء مسیریابی، باید مقدار دهی شود. همچنین قصد داشتیم اطلاعاتی را نیز به کامپوننت مورد نظر ارسال کنیم؛ همانند مکانیزم مسیریابی که با پارامترها این چنین کارهایی صورت میپذیرد. در اینجا از یک کلاس به شکل زیر استفاده شدهاست:
export class IdModel { constructor(public id: number) {} }
در این صورت پیاده سازی LazyComponent نیز به شکل زیر خواهد بود:
import { Component, OnInit } from '@angular/core'; import { IdModel } from './../core/models/id-model'; @Component({ selector: 'app-lazy', templateUrl: './lazy.component.html', styleUrls: ['./lazy.component.scss'] }) export class LazyComponent implements OnInit { constructor(private model: IdModel) {} ngOnInit() { console.log(this.model); } }
البته فراموش نکنید کامپوننتی را که نیاز است به صورت پویا بارگذاری شود، در قسمت entryComponents مرتبط با NgModule متناظر به شکل نیز معرفی کنید:
import { CommonModule } from '@angular/common'; import { LazyComponent } from './lazy.component'; import { NgModule } from '@angular/core'; @NgModule({ imports: [CommonModule], declarations: [LazyComponent], entryComponents: [LazyComponent] }) export class LazyModule {}
با خروجی زیر:
و chunk تولید شده برای ماژول مورد نظر:
در صورتیکه در حالت production پروژه را بیلد کنید، هش مرتبط برای chunk تولید شده نیز ایجاد خواهد شد.
کدهای کامل این قسمت را میتوانید از اینجا دریافت کنید.
Learn FULL STACK Web Development in 2 HOURS! ASP.NET & Angular
Timestamps:
00:00:00 Welcome to our 2 hour FULL STACK Course!
00:01:12 What you will learn during the next 2 hours
00:03:29 Day 1 Multi-Page and Single-Page Applications, TypeScript, and Angular Components
00:21:57 Day 2 One-Way Binding and Event Binding in Angular
00:34:23 Day 3 Our Flight Booking Portal and routing in Angular
00:44:52 Day 4 The 'Search Flight' page, Design a HTML page, install Font Awesome using Node, and TypeScript interfaces
01:27:00 Day 5 ASP.NET Core REST API, SWAGGER for documenting and testing our API
01:55:51 Thanks for watching!