اضافه کردن HTTPS به وب سایت
Angular CLI - قسمت سوم - تولید کد
برای لغو این حالت میتوان از ViewEncapsulation.None استفاده کرد:
@Component({ // ... encapsulation: ViewEncapsulation.None,
- حالت Native: نه HTML و نه کامپوننتها، بر روی شیوهنامههای یکدیگر تاثیر نمیگذارند.
- حالت None: شیوهنامههای یک کامپوننت به کل برنامه منتشر شده و بر روی آن تاثیری میگذارند.
علت نیاز به گروه بندی مسیریابیها در ذیل یک مسیریابی بدون کامپوننت
علت وجود امکان گروه بندی مسیریابیها، در ذیل یک مسیریابی بدون کامپوننت به شرح زیر هستند:
- امکان مدیریت و ساماندهی سادهتر مسیریابیها با افزایش حجم برنامه
- امکان به اشتراک گذاری Route Resolvers و محافظت کنندههای از مسیرها
- ممکن ساختن امکان lazy loading آن گروه
گروه بندی مسیریابیها
در حال حاضر، مسیریابی ماژول محصولات مثال این سری، یک چنین تعاریفی را پیدا کردهاست:
const routes: Routes = [ { path: 'products', component: ProductListComponent }, { path: 'products/:id', component: ProductDetailComponent, resolve: { product: ProductResolverService } }, { path: 'products/:id/edit', component: ProductEditComponent, resolve: { product: ProductResolverService }, children: [ ] } ];
const routes: Routes = [ { path: 'products', children: [ { path: '', component: ProductListComponent }, { path: ':id', component: ProductDetailComponent, resolve: { product: ProductResolverService } }, { path: ':id/edit', component: ProductEditComponent, resolve: { product: ProductResolverService }, children: [ { path: '', redirectTo: 'info', pathMatch: 'full' }, { path: 'info', component: ProductEditInfoComponent }, { path: 'tags', component: ProductEditTagsComponent } ] } ] } ];
- ابتدا دو مسیریابی نمایش جزئیات و ویرایش یک محصول، تبدیل به یک گروه، به صورت فرزندان مسیریابی products با تعریف خاصیت children آن شدهاند.
- سپس pathهای آنها ویرایش شده و با حذف /product از ابتدای آنها، حالت نسبی را پیدا کردهاند.
- مسیریابی products که والد این مسیریابیهای فرزند است نیز بدون کامپوننت تعریف شدهاست.
- کامپوننت مسیریابی products، به عنوان مدیریت کنندهی مسیر پیش فرض این فرزندان، تعریف شدهاست.
Child routes در درون router-outlet تعریف شدهی درون قالب والد آنها نمایش داده میشوند (مانند برگههای edit info و edit tags قسمت قبل). با توجه به اینکه اکنون دو مسیریابی دیگر، به صورت فرزندان مسیریابی صفحهی نمایش لیست محصولات تعریف شدهاند، به همین جهت باید یک router-outlet جدید را در درون قالب کامپوننت نمایش لیست محصولات، تعریف کرد. اما نمیخواهیم نمایش جزئیات یک محصول و یا صفحهی ویرایش آنها، در همان صفحهی نمایش لیست محصولات ظاهر شوند. برای رفع این مشکل است که نیاز به تعریف یک مسیریابی بدون کامپوننت خواهیم داشت. به همین جهت در تعاریف فوق، تعریف component: ProductListComponent به یکی از مداخل آرایهی children منتقل شدهاست (بجای تعریف آن همانند قبل ذیل مسیریابی products) که دارای path خالی است (یا همان مسیر پیش فرض که در اینجا به products اشاره میکند).
در این حالت چون مسیریابی والد، به همراه یک کامپوننت تعریف نشدهاست، مسیریاب، سعی در نمایش فرزندان آن در router-outlet والد نمیکند. بجای آن، فرزندان، در یک router-outlet قرار گرفتهی در یک سطح بالاتر، نمایش داده میشوند که دقیقا همان router-outlet تعریف شدهی در فایل قالب src\app\app.component.html است.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید: angular-routing-lab-05.zip
برای اجرای آن فرض بر این است که پیشتر Angular CLI را نصب کردهاید. سپس از طریق خط فرمان به ریشهی پروژه وارد شده و دستور npm install را صادر کنید تا وابستگیهای آن دریافت و نصب شوند. در آخر با اجرای دستور ng s -o برنامه ساخته شده و در مرورگر پیش فرض سیستم نمایش داده خواهد شد.
ASP.NET Core 6 Preview 5 منتشر شد
Here’s what’s new in this preview release:
- .NET Hot Reload updates for
dotnet watch
- ASP.NET Core SPA templates updated to Angular 11 and React 17
- Use Razor syntax in SVG
foreignObject
elements - Specify null for
Action
andRenderFragment
component parameters - Reduced Blazor WebAssembly download size with runtime relinking
- Configurable buffer threshold before writing to disk in Json.NET output formatter
- Subcategories for better filtering of Kestrel logs
- Faster get and set for HTTP headers
- Configurable unconsumed incoming buffer size for IIS
React 16x
- قسمت 1 : معرفی و شروع به کار
- قسمت 2 : بررسی پیشنیازهای جاوا اسکریپتی - بخش 1
- قسمت 3 : بررسی پیشنیازهای جاوا اسکریپتی - بخش 2
- قسمت 4 : کامپوننتها - بخش 1 - کار با عبارات JSX
- قسمت 5 : کامپوننتها - بخش 2 - نمایش لیستها و مدیریت رویدادها و حالات
- قسمت 6 : کامپوننتها - بخش 3 - یک تمرین
- قسمت 7 : ترکیب کامپوننتها - بخش 1 - ارسال دادهها، مدیریت رخدادها
- قسمت 8 : ترکیب کامپوننتها - بخش 2 - مدیریت state
- قسمت 9 : ترکیب کامپوننتها - بخش 3 - Lifecycle Hooks
- قسمت 10 : ترکیب کامپوننتها - بخش 4 - یک تمرین
- قسمت 11 : طراحی یک گرید - بخش 1 - کامپوننت صفحه بندی
- قسمت 12 : طراحی یک گرید - بخش 2 - فیلتر کردن اطلاعات
- قسمت 13 : طراحی یک گرید - بخش 3 - مرتب سازی اطلاعات
- قسمت 14: طراحی یک گرید - بخش 4 - پویاسازی تعاریف ستونها
- قسمت 15 :مسیریابی - بخش 1 - تعریف و تنظیم مسیریابیها
- قسمت 16 : مسیریابی - بخش 2 - پارامترهای مسیریابی
- قسمت 17 : مسیریابی - بخش 3 - یک تمرین
- قسمت 18 : کار با فرمها - بخش 1 - دریافت ورودیها از کاربر
- قسمت 19 : کار با فرمها - بخش 2 - اعتبارسنجی ورودیهای کاربران
- قسمت 20 : کار با فرمها - بخش 3 - بهبود کیفیت کدهای فرم لاگین
- قسمت 21 : کار با فرمها - بخش 4 - چند تمرین
- قسمت 22 : ارتباط با سرور - بخش 1 - برپایی تنظیمات
- قسمت 23 : ارتباط با سرور - بخش 2 - شروع به کار با Axios
- قسمت 24 : ارتباط با سرور - بخش 3 - نکات تکمیلی کار با Axios
- قسمت 25 : ارتباط با سرور - بخش 4 - یک تمرین
- قسمت 26 : احراز هویت و اعتبارسنجی کاربران - بخش 1 - ثبت نام و ورود به سیستم
- قسمت 27 : احراز هویت و اعتبارسنجی کاربران - بخش 2 - استخراج و نمایش اطلاعات JWT و خروج از سیستم
- قسمت 28 : احراز هویت و اعتبارسنجی کاربران - بخش 3 - فراخوانی منابع محافظت شده و مخفی کردن عناصر صفحه
- قسمت 29 : احراز هویت و اعتبارسنجی کاربران - بخش 4 - محافظت از مسیرها
- قسمت 30 : React Hooks - بخش 1 - معرفی useState و useEffect
- قسمت 31 : React Hooks - بخش 2 - مقایسه حالتهای مختلف مدیریت حالت با useState Hook
- قسمت 32 : React Hooks - بخش 3 - نکات ویژهی برقراری ارتباط با سرور
- قسمت 33 : React Hooks - بخش 4 - useContext Hook
Redux
- قسمت اول : Redux چیست؟
- قسمت دوم : بررسی توابع Redux
- قسمت سوم : روش اتصال Redux به برنامههای React
- قسمت چهارم : انجام اعمال async با Redux
- قسمت پنجم : Redux Hooks
- قسمت ششم : MobX چیست؟
- قسمت هفتم : بررسی مفاهیم Mobx
- قسمت هشتم : تنظیمات پروژههای React برای کار با Mobx decorators
- قسمت نهم : مثالی از کتابخانهی mobx-react
- قسمت دهم : MobX Hooks و اعمال Async در Mobx
- ساخت یک مثال Todo با MobX و React
- روش یکی کردن پروژههای React و ASP.NET Core
- آپلود فایلها توسط برنامههای React به یک سرور ASP.NET Core به همراه نمایش درصد پیشرفت
- روش کار با فایلهای ایستا در برنامههای React
- روش کار با فایلهای پویای ارائه شدهی توسط یک برنامهی ASP.NET Core در برنامههای React
- استفاده از قالب مخصوص Redux Toolkit جهت ایجاد پروژههای React/Redux
- تبدیل یک قالب HTML معمولی به قالب React
- React component lifecycle
- React reconciliation
Automapper به بنیاد NET. پیوست.
AutoMapper has been a popular library in the .NET open source community for a long time. As their site says:
AutoMapper is a simple little library built to solve a deceptively complex problem - getting rid of code that mapped one object to another. This type of code is rather dreary and boring to write, so why not invent a tool to do it for us?
Microbenchmark testing Python, Numba, Mojo, Dart, C/gcc, Rust, Go, JavaScript, C#, Java, Kotlin, Pascal, Ruby, Haskell performance in Mandelbrot set generation
Benchmarking several languages/tools with Mandelbrot set generation. 1-to-1 translation of code from one language to another. No SIMD, no multithreading (except prange() trick with Numba), no tricks (e.g. skipping sqrt), a bare minimum of language specific adjustments to make the code nicer while keeping all loops and operations in place.
در نسخههای قبل از 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 تولید شده نیز ایجاد خواهد شد.
کدهای کامل این قسمت را میتوانید از اینجا دریافت کنید.