Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Angular Fundamentals Summary

Tech May 31 1
  • Create project: ng new projectName
  • Start project: ng serve --open
  • Create component: ng g c directory/componentName
  • Create module: ng g m directory/moduleName
  • Create service: ng g s directory/serviceName
  1. Angular Project Directory Analysis

  1. Initial Angular Modules

2.1 Contents Included in a Module:

  • Components
  • Services
  • Directives
  • Note: The above three must be configured in the module before they can be used!

2.2 Example

  • Use ng g m todo-list to create the todo-list module
  • Use ng g c todo-list/componentName to create two components in that directory

2.3 Exporting and Importing Modules

  1. Directives

3.1 Interpolation {{ }}

3.2 Property Binding

  • [propertyName] = "data" or

  • propertyName = "{{ data }}" or

  • `propertyName = "string"

  • With [ ], or without [ ], using {{ }}, indicates that data is a variable

  • Without [ ], indicates that string is a string

3.3 Event Binding

  • Regular event binding: (click) = "handleClick()"
  • Event binding with event object: (click) = "handleClick($event)", template usage as follows:
handleClick(e){
    console.log(e)
    e.preventDefault()//prevent default behavior
}

3.4 Two-way Data Binding

  • [(ngModel)] = "modelData"
  • Note: The [(ngModel)] directive is in the Angular FormsModule module, which needs to be imported into the module before use

3.5 [ngClass]

  • Operate a class name
//html
<p [class.redColor] = "isRed">111</p>

//ts
isRed = true;

//css
.redColor{
    color:red;
}
  • Operate multiple class names
//html
<p [ngClass] = "classObj">ceshi</p>

//ts
classObj = {
    redColor: true,
    myFontSize: false
}

css
.color{
    color:red;
}

.myFontSize{
    font-size:12px;
}

3.6 [ngStyle]

  • Operate one style
//html
<p [style.color] = "colorName">111</P>

//ts
colorName = 'red';
  • Operate multiple styles
//html
<p [ngStyle] = "styleObj">111</P>

//ts
styleObj = {
    color: 'red',
    fontSize:'12px'
}

3.7 *ngIf

  • HTML: <h1 *ngIf = "isShow">111</h1>
  • TS: isShow = false;

3.8 *ngFor

  • Iterate over a normal array: <i *ngFor = "let item of Arrys; let i = index; let isOdd = odd"> {{ item }}--{{ i }}--{{ isOdd ? 奇 : 偶 }} </i>
  • Iterate over an object array: benefit, improve rendering performance.
//html add trackBy means tracking self, so when part of the object list changes, only the changed data is re-rendered
<i *ngFor="let item of nameList; trackBy: trackById"></i>

//ts
nameList = [
    { id: 1, name: 'xiaoming' },
    { id: 2, name: 'xiaohuang' },
    { id: 3, name: 'xiaolan' }
]

//add this method
trackById(i:number,item:any){
    return item.id
}
  1. Component Nesting

//Parent component uses child component, need to import and declare in the parent module.ts file:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ChildComponent } from './child/child.component'; //import

@NgModule({
  declarations: [
    AppComponent,
    ChildComponent //declare
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  1. Component Communication

5.1 Parent to Child

//Parent component

//html
<!-- Parent component uses child component and passes data to it -->
<app-child [myProp] = 'prop'></app-child>

//ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.less']
})
export class AppComponent {
  prop = 'fatherData'
}
//Child component

//ts
import { Component, Input, OnInit } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.less']
})
export class ChildComponent implements OnInit {

  constructor() { }

  // Receive data passed from parent component
  // Need to use Input to declare, note that Input must be imported above
  @Input()
  myProp:any

  ngOnInit(): void {
  }
}

5.2 Child to Parent

//Child component

import { Component, Output,EventEmitter, OnInit } from '@angular/core';

@Component({
  selector: 'app-child',
  templateUrl: './child.component.html',
  styleUrls: ['./child.component.less']
})
export class ChildComponent implements OnInit {

  constructor() { }

  // Data to transmit
  childData = 'someData'

  // 1. Child component creates a custom EventEmitter event
  @Output()
  put = new EventEmitter()

  // 3. Child component triggers the custom event, thus triggering the parent component's receiving event
  handleClick(){
    this.put.emit(this.childData) // parameter is the data to be transmitted
  }

  ngOnInit(): void {
  }
}
//Parent component
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  // 2. In the parent component, use the child component's custom event and bind the receiving function
  template: `<app-child (put)="get($event)"></app-child>`,
  styleUrls: ['./app.component.less']
})
export class AppComponent {

  mydata:any

  // 4. Receiving data processing function
  get(data:any){
    this.mydata = data
  }
}
  1. Services

6.1 Explanation of Service Role

  • Components should only provide properties and methods for data binding
  • Components should not define operations such as requesting data, user validation, etc.
  • Various processing tasks should be defined in injectable services
  • Service role: handle business logic, available for components

6.2 Service Description

  • Use @Injectable() decorator to indicate a service
  • Services need to register providers to be used
  • Angular provides services to components through dependency injection (DI), i.e., components inject service dependencies without manual creation
  • Recommended to register services used in the component in the constructor

6.3 Three Ways to Register Service Providers

(1) In the service file, register the service as a root provider via @Injectable() providedIn: 'root', making it available to all components in the project

  • Inject and register the required service in the component, as shown below:

(2) In the module file, register as a provider of the module via @NgModule() providers: [], available only to components within the module

  • Inject and register the required service in the component, as shown below:

(3) In the component file, register as a provider only available to the component and its subcomponents via @Component's providers: []

  1. HttpClient Description

Function: Send HTTP requests

  • Wraps the XMLHttpRequest interface provided by the browser
  • Uses an observable-based API
  • Provides a streaming error handling mechanism for requests and responses

7.1 Using HttpClient

7.2 Get Full HTTP Resposne Content

// Add { observe: 'response' } after the request address
getData() {
  this.http
     .get('../../../assets/myData.json', { observe: 'response' })
     .subscribe((res) => {
       console.log(res); // All response content
       console.log(res.body); // Response body
       console.log(res.headers); // Response headers
       console.log(res.headers.get('content-type')); // Response data type
       console.log('etc');
  });
}

7.3 Using TS Syntax to Constrain Response Data

  • Constrain the get request and response res:

7.4 Request Failure Callback

getData() {
  this.http.get<resInterface>('../../../assets/myData.json1').subscribe(
    (res: resInterface) => {
      console.log(res); // All response content
    },
    (err) => {  // Failure callback
      console.log(err);
    }
  );
}

7.5 Using json-server Plugin to Simulate Backend Interface

    1. Install: npm i -g json-server
    1. Create a json file, such as db.json
    1. Run json-server: json-server db.json
    1. Request as follows:
get('url address')
post('url address',{parameter: 'value'})
delete(`{$this.url}/id value`)
patch(`{$this.url}/id value`,{parameter: 'new value'})
  1. Routing

8.1 Basic Steps to Configure Routing

  • In the module file:
import { MyComp1Component } from "./my-module/my-comp1/my-comp1.component";//Import component
// 1. Import routing module
import { RouterModule, Routes } from "@angular/router";
// 2. Configure routing rules, and use Routes to constrain the routing format
const appRouters: Routes = [
  {
    path: 'mycomp1',
    component: MyComp1Component
  }
]
@NgModule({
  declarations: [
    AppComponent,
    MyComp1Component,//Import the component used for routing display
  ],
  imports: [
    // 3. Configure the routing module, forRoot() ensures single routing service, preventing routing service errors
    RouterModule.forRoot(appRouters)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  • HTML file routing outlet
<!-- 4. Configure route navigation -->
<button routerLink="/mycomp1">Display myComp1 component</button>
<!-- 5. Configure route outlet -->
<router-outlet></router-outlet>

8.2 Default Route, Redirection, Wildcard Route

const appRouters: Routes = [
  {
    // Default route, redirection
    path: '',
    redirectTo: '/mycomp1',
    pathMatch: 'full'
  },
  {
    // Wildcard route, redirect to 404 page when accessing non-existent route
    path: '**',
    component: NotFoundError
  },
  {
    path: 'mycomp1',
    component: MyComp1Component
  }
]

8.3 Route Parameters

// One, configure the route file:
const appRouters: Routes = [
  {
    // Route parameters
    // Can match: /perName/1 /perName/2 ...
    // Cannot match: /perName /perName/1/1 ...
    path: 'perName/:id',
    component: PerNameComponent
  }
]

// Two, navigation HTML
<button routerLink="/perName/1">Click 1</button>
<button routerLink="/perName/2">Click 2</button>

// Three, route component TS file
// 1. Import routing service
import { ActivatedRoute } from '@angular/router'

export class PerNameComponent implements OnInit {
  constructor(
    // 2. Declare
    private route: ActivatedRoute
  )
     
  selectObj = [
      { id:1, name: 'xiaoming' },
      { id:2, name: 'xiaolan' }
  ]
   
  activeName:any

  ngOnInit(){
      this.route.paramMap.subscribe(param => {
          console.log(param)
          const id = param.get('id')//Get route parameter
          this.activeName = this.selectObj.find(item => item.id === +id) // Convert string type id to number type
}
                                 
// Four, route component HTML
<div>{{ activeName }}</div>                        

8.4 Nested Routing

// Route configuration file
const appRouters: Routes = [
  {
    path: 'father',
    component: MyComp1Component,
    // Sub-route
    children: [
        path: 'child1',
        component: Child1Component
    ]
  }
]

// HTML
<a routerLink = "/father/child1">Click</a>
<router-outlet></router-outlet>

8.5 Route Highlighting

// HTML
<a routerLink="/mycomp1" routerLinkActive="actived">Click 1</a>
<a routerLink="/mycomp2" routerLinkActive="actived">Click 1</a>
// Indicates exact match
<a routerLink="/mycomp3" routerLinkActive="actived" [routerLinkActiveOptions]="{exact: true}"></a>

// css
.actived {
    color:red
}
  1. Programmatic Navigation

// 1. Import Router
import { Router } from '@angular/router'

export class MyComp1Component implements OnInit {
  constructor(
    // 2. Declare
    private router: Router
  ) {}
  // 3. Use
  goTo() {
    this.router.navigate(['/mycomp1'])
  }
  ngOnInit(): void {
       
  }
}
  1. Reactive Forms

  • Reactive forms (key point)
  • Template-driven forms (based on template syntax, and two-way data binding directives, such as Angular's [ngModel], Vue's v-model)

Basic Usage Steps:

// One, module file:
// 1. Import
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  declarations: [
  ],
  imports: [
    // 2. Declare
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

// Two, TS file
import { Component } from '@angular/core';
// 3. Import
import { FormControl } from '@angular/forms'

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.less']
})
export class AppComponent {
  // 4. New
  username = new FormControl('zrh')
  password = new FormControl('123456')
    
  // Get value
  console.log(this.username.value)
  // Update value
  setUsername() {
      this.username.setValue('newName')
  }
}

// Three, HTML
<label>
  Username:
  <input type="text" [formControl]="username">
</label>
<p>{{username.value}}</p>
<label>
  Password:
  <input type="password" [formControl]="password">
</label>
<p>{{password.value}}</p>

For more information, please refer to the official documentation!

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.