تمام مسیریابیهای این سری به نگارش سوم روتر AngularJS 2.0 به روز رسانی شدند.
ریز جزئیات تغییرات
توضیحات:
ابتدا نیاز است وابستگیهای روتر جدید را به نحو ذیل به فایل package.json اضافه کنید:
"dependencies": { // ... "@angular/router": "^3.0.0-alpha.7", // ... },
یک فایل جدید را به نام app.routes.ts به ریشهی پروژه اضافه کنید، با این محتوا
import { provideRouter, RouterConfig } from '@angular/router'; import { ProductListComponent } from './products/product-list.component'; import { WelcomeComponent } from './home/welcome.component'; import { ProductDetailComponent } from './products/product-detail.component'; import { ProductFormComponent } from './products/product-form.component'; import { SignupFormComponent } from './users/signup-form.component'; import { TypedShaComponent } from './using-third-party-libraries/typed-sha.component'; import { UnTypedShaComponent } from './using-third-party-libraries/untyped-sha.component'; import { UsingJQueryAddonsComponent } from './using-jquery-addons/using-jquery-addons.component'; export const routes: RouterConfig = [ { path: '', component: WelcomeComponent }, { path: 'welcome', component: WelcomeComponent }, { path: 'products', component: ProductListComponent }, { path: 'product/:id', component: ProductDetailComponent }, { path: 'addproduct', component: ProductFormComponent }, { path: 'adduser', component: SignupFormComponent }, { path: 'typedsha', component: TypedShaComponent }, { path: 'untypedsha', component: UnTypedShaComponent }, { path: 'usingjquery', component: UsingJQueryAddonsComponent } ]; export const APP_ROUTER_PROVIDERS = [ provideRouter(routes) ];
در سیستم مسیریابی جدید، خاصیتهای name و useAsDefault وجود ندارند و حذف شدهاند. همچنین مسیریابیها نباید با / شروع شوند.
به علاوه در فایل index.html، مسیر ریشه به نحو ذیل مشخص میشود:
<base href=".">
// ... import { APP_ROUTER_PROVIDERS } from './app.routes'; // ... bootstrap(AppComponent, [ // ... APP_ROUTER_PROVIDERS ]) .catch(err => console.error(err));
البته باید دقت داشت که فایل systemjs.config.js هم کمی نیاز است جهت بارگذاری این مسیریاب جدید اصلاح شود.
در ادامه، در فایل app.component.ts، دایرکتیوهای مرتبط با مسیریابی که در ROUTER_DIRECTIVES قرار دارند، اینبار از ماژول ذیل تامین میشوند:
import { ROUTER_DIRECTIVES } from '@angular/router';
سپس لینکهای مسیریابی، اینبار بجای نام مسیریابی که در نگارش سوم روتر، حذف شدهاست، به همان مسیر متناظر اشاره میکند:
<a [routerLink]="['/welcome']">Home</a>
this._router.navigate(['/products']);
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router, ActivatedRoute } from '@angular/router'; @Component({ templateUrl: 'app/products/product-detail.component.html' //template: require('./product-detail.component.html')//for webpack }) export class ProductDetailComponent implements OnInit, OnDestroy { private sub: any; pageTitle: string = 'Product Detail'; constructor(private _route: ActivatedRoute, private _router: Router) { } ngOnInit(): void { this.sub = this._route.params .subscribe(params => { let id = +params['id']; // (+) converts string 'id' to a number this.pageTitle += `: ${id}`; }); } ngOnDestroy(): void { this.sub.unsubscribe(); // we must unsubscribe before Angular destroys the component. Failure to do so could create a memory leak. } onBack(): void { this._router.navigate(['/products']); } }
یک اصلاح دیگر هم در اینجا داریم. لینک به صفحهی جزئیات هر محصول اینبار به صورت زیر ویرایش میشود (در فایل product-list.component.html):
<a [routerLink]="['/product', product.productId]"> {{product.productName}} </a>
آشنایی با Refactoring - قسمت 3
public class OrderLineItem : Entity { /// <summary> /// many-to-one from OrderLineItem to Order /// </summary> public virtual Order Order { get; set; } /// <summary> /// Money is a component, not a separate entity; i.e., the OrderLineItems table will have /// column for the amount /// </summary> public virtual Money Price { get; set; } /// <summary> /// many-to-one from OrderLineItem to Product /// </summary> public virtual Product Product { get; set; } public virtual int Quantity { get; set; } /// <summary> /// Example of adding domain business logic to entity /// </summary> public virtual Money GetTotal() { return new Money(Price.Amount * Quantity); } }
The first version of ASP.NET was released 17 years ago and during these years, it is fascinating to see how the ASP.NET team constructively reacted through these years to the major shifts happening on the web. Initially a platform that was closed and tried to hide and abstract the web; ASP.NET has metamorphized into an open source and cross platform - one that fully embraces the nature of the web. This is the first part of a series of 3 articles that will cover the history of ASP.NET from its launch to the latest ASP.NET Core releases.
سری آموزشی Blazor C# Tutorials
Blazor C# Tutorials
30 videos
In this playlist, I am going through all the fundamentals and sharing my journey to be a full stack Blazor developer. This is the future of web development in ASP.NET world. If you want to learn Blazor this is the best place to start.
1. Build Your First App - EP01
2. Getting Started - EP02
3. #Routing - EP03
4. Dependency #Injection - EP04
5. Forms & #Validations - EP05
6. JavaScript #Interop - EP06
7. #Razor #Components | Re-usability - EP07
8. Razor Components | #Lifecycle Methods - EP08
9. Razor Component #Libraries - EP09
10. Call #REST #API - #CRUD Methods - EP10
11. #Authentication | Out of the box- EP11
12. Custom AuthenticationStateProvider - EP12
13. Layouts | Login Pages - EP13
14. HttpClient | Login User
15. IHttpClientFactory | Login User
16. Sending JWT token & Request Middleware
17. Handling Exceptions
دوره و کتاب رایگان Angular 5
Learn Blazor WebAssembly and Web API on .NET 6 by building a shopping cart application using C#. This course also provides a guide on how to integrate a payment gateway into your Blazor WebAssembly component, so that a user is able to pay for products through your application using a debit or credit card or PayPal account.
⭐️ Course Contents ⭐️
⌨️ (0:00:00) Introduction
⌨️ (0:00:51) Create the Database using EF Core Code First Database Migrations
⌨️ (0:26:05) Retrieve Product Data from Database (Web API component)
⌨️ (0:30:17) Create Classes for Data Transfer Objects (DTOs)
⌨️ (0:36:22) Create ProductRepository Class (Repository Design Pattern)
⌨️ (0:43:05) Create ProductController Class
⌨️ (0:51:08) Create DtoConversion Class (DTO Conversion Extension methods)
⌨️ (0:57:45) Display Product Data to User (Blazor WebAssembly Component)
⌨️ (1:39:59) Display Data for Specific Product to User (Web API and Blazor)
⌨️ (2:06:07) Add Product to Shopping Cart (Web API and Blazor)
⌨️ (2:52:40) Remove Product from Shopping Cart (Web API and Blazor)
⌨️ (3:14:03) Update the Quantity of Products in the Shopping Cart (Web API, Blazor, Blazor JavaScript Interoperability)
⌨️ (3:44:01) Update the Header Menu in Response to a Change to the State of the Shopping Cart (Creating Custom Events in Blazor)
⌨️ (4:04:48) Integration of PayPal Payment Gateway into Blazor Component
⌨️ (4:36:03) Dynamically Populate the Side-Bar Menu (Web API and Blazor)
⌨️ (5:05:44) Optimise Code for Performance (Web API and Blazor)
⌨️ (5:08:26) Use Include Extension Method in LINQ Query (Web API)
⌨️ (5:14:00) User Local Storage Functionality (Blazor)
⌨️ (5:35:42) Outro
import { HttpClient } from "@angular/common/http"; import { Injectable } from "@angular/core"; @Injectable() export class AppConfigService { private config: IAppConfig; constructor(private http: HttpClient) { } loadClientConfig(): Promise<any> { return this.http.get<IAppConfig>("assets/client-config.json") .toPromise() .then(config => { this.config = config; console.log("Config", this.config); }) .catch(err => { return Promise.reject(err); }); } get configuration(): IAppConfig { if (!this.config) { throw new Error("Attempted to access configuration property before configuration data was loaded."); } return this.config; } } export interface IAppConfig { apiEndpoint: string; loginPath: string; logoutPath: string; refreshTokenPath: string; accessTokenObjectKey: string; refreshTokenObjectKey: string; adminRoleName: string; }
و تغییر ماژول CoreModule به شکل زیر :
import { NgModule, Optional, SkipSelf, APP_INITIALIZER } from "@angular/core"; import { CommonModule } from "@angular/common"; import { RouterModule } from "@angular/router"; import { HTTP_INTERCEPTORS } from "@angular/common/http"; // import RxJs needed operators only once import "./services/rxjs-operators"; import { HeaderComponent } from "./component/header/header.component"; import { AuthGuard } from "./services/auth.guard"; import { AuthInterceptor } from "./services/auth.interceptor"; import { AuthService } from "./services/auth.service"; import { AppConfigService } from "./services/app-config.service"; import { BrowserStorageService } from "./services/browser-storage.service"; @NgModule({ imports: [CommonModule, RouterModule], exports: [ // components that are used in app.component.ts will be listed here. HeaderComponent ], declarations: [ // components that are used in app.component.ts will be listed here. HeaderComponent ], providers: [ // global singleton services of the whole app will be listed here. BrowserStorageService, AppConfigService, AuthService, AuthGuard, { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }, { provide: APP_INITIALIZER, useFactory: (config: AppConfigService) => () => config.loadClientConfig(), deps: [AppConfigService ], multi: true } ] }) export class CoreModule { constructor( @Optional() @SkipSelf() core: CoreModule) { if (core) { throw new Error("CoreModule should be imported ONLY in AppModule."); } } }
Cannot instantiate cyclic dependency! ApplicationRef ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1