Overview

The second chapter of the Angular Sinkhole Notes introduces the concepts of components and how components are used to implement system functions in Angular.

Corresponding official document address:

  • Display the data
  • Template syntax
  • User input
  • Interactions between components
  • The pipe
  • Lifecycle hook

Address: Angular-practice/SRC/component-guide

Contents

  1. Angular from pit to pit – Getting Started with Angular usage
  2. Angular From Pothole to Pothole – Component eating Guide

Knowledge Graph

Step by Step

Components and Templates

Basic concepts of components

A component contains a set of specific functions. Each component has a single, independent function that can be reused. Components can be created using the Angular CLI under the SRC /app/ path of the workspace

#Create a product-list component
ng g component product-list
Copy the code

When you need to place components in a specified directory, you can add the path directly in the ng g command

#Generate the Hero component to the Components path
ng g component components/hero
Copy the code

An Angular application is a component tree made up of components, each consisting of the following four parts

  • Product-list.component.ts: Component classes that handle data and functionality to support view rendering
  • Product-list.component. HTML: the HTML template of the corresponding page of the component, which is used to present the functionality of the component
  • Product-list.component. SCSS: styles for the current component only
  • Product-list.component.spec.ts: unit test file for the current component (optional)

When a new component is created from the command line, it is automatically registered with the root module (app.module.ts) of the application

In a Component class, the @Component decorator [1] is used to declare the class as a Component class and configure the Component class with some metadata [2] to determine how the Component should be processed, instantiated, and used at runtime

There are three basic configuration parameters in the decorator that are used to associate components with views

  • 15. selector: when we add the label specified by that selector to a page (<app-product-list></app-product-list>), an instance of the component is created and inserted at the current usage location
  • TemplateUrl: Address of the HTML template file that corresponds to this component
  • StyleUrls: the CSS style file address that is unique to this component view

When you need to use this component, you simply add the label corresponding to the selector to the page

Template binding syntax

In An Angular application, a component acts as a controller or viewmodel and is associated with an HTML file that is a basic Angular template file when the component is created

In this template file, we can combine HTML elements with Angular’s built-in template syntax to tell Angular how to render a page based on our application logic and data

Interpolation expression

Interpolation can be used to evaluate property values in a component or data on a template using template expression operators to render the values to a view page

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

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {

  public title = 'I'm the title property value';

  constructor() { }

  ngOnInit(): void{}}Copy the code
<p>Title: {{title}}</p>

<p>1 + 2 + 3 + 4 + 5 = {{1 + 2 + 3 + 4 + 5}}</p>
Copy the code

The variable source of the template expression

  • Variables of the template itself
  • The context variable of the instruction
  • Component member information (properties or methods)

When using a template expression, the template variable takes precedence if the variable name exists from more than one source, followed by the context variable of the directive, and finally the member of the component

The following principles should be followed when using template expressions

  • Simple: Normally, business logic or data operations should be put into components, and template expressions are only used as property or method calls
  • Fast execution: The data generated by a template expression should end quickly, otherwise it will have an impact on the user experience
  • There are no visible side effects: template expressions serve only as data representations and should not change any data; You should build idempotent expressions that return the same data information multiple times unless the dependent values change
Template binding syntax

Through data binding mechanism, data source and view are bound to achieve consistency between source data and user presentation

  • From data source to view: interpolation, properties in components, property [3] of DOM elements, CSS styles, CSS classes
  • From view to data source: events
  • Bidirectional binding between view and data source: data object
classification grammar
A one-way

From data source to view
1, interpolation: {{expression}}

2. Bind with [] :<a [href]='expression'></a>

3. Use bind to bind:<a bind-href='expression'></a>
A one-way

From view to data source
1. Bind with () :<a (click)='statement'></a>

2. Bind with ON:<a on-click='statement'></a>
two-way

View to data source; Data source to view
1. Bind with [()] :<input type="text" [(ngModel)]="product.Name">

2. Bind with bindon:<input type="text" bindon-ngModel="product.Name">
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {

  public title = 'I'm the title property value';
    
  public styleProperty = ' I'm an attribute that contains an HTML tag ';

  public fontColor = 'red';

  public url = 'https://yuiter.com';

  public name: string;

  constructor() { }

  ngOnInit(): void {
  }

  getUser() {
    alert('111111111'); }}Copy the code
<h3>2.1. From data source to view</h3>

<p>
  <a href='{{url}}'>Use interpolation expressions for binding</a>
</p>
<p>
  <a [href] ='url' [style.color] ='fontColor'>Bind with []</a>
</p>
<p>
  <a bind-href='url'>Use bind for binding</a>
</p>
<p>
  <span [innerHtml] ="styleProperty"></span>
</p>

<h3>2.2. From View to data source</h3>

<p>
  <button (click) ="getUser()">Use () for binding</button>
</p>
<p>
  <button on-click="getUser()">Use on for binding</button>
</p>

<h3>Data binding - A reference to FormsModule needs to be added to the AppModule</h3>

<p>
  <input type="text" id="userName" [(ngModel)] ="name">
</p>
<p>
  <input type="text" bindon-ngModel="name">
</p>
Copy the code

Data binding
  • One-way data binding

    <p>{{title}}</p>
    Copy the code
  • Two-way data binding

    <input type="text" id="userName" [(ngModel)] ="name">
    
    <! -- Bidirectional data binding is equivalent to the following when there is no NgModel
    <input type="text" id="userName" [value] ="name" (input) ="name=$event.target.value">
    Copy the code
Property, style binding
  • Property binding for dom elements

    <img [src] ="productImageUrl">
    
    <img bind-src="productImageUrl">
    Copy the code
  • Attribute binding of HTML tags

    The syntax of an attribute binding is similar to that of a property binding, consisting of the prefix attr, point (.), and attribute name

    One of the main use cases for attribute binding is setting ARIA Attributes (for people with disabilities)

    <button [attr.aria-label] ="actionName">{{actionName}} with Aria</button>
    Copy the code
  • Style inline style binding

    / / 1, [style. The width] = "width: string | undefined | null
    public width = "100px";
    
    / / 2, [style. The width. The px] = "width:" number | undefined | null
    public width = "20";
    
    // 3, [style]="styleExpr" : string
    public styleExpr = "width: 100px; color:red";
    
    // 4, [style]="styleExpr" : {key:value}
    public styleExpr = {width: '100px', height: '100px'};
    
    // 5, [style]="styleExpr" : array
    public styleExpr = ["width"."100px"];
    Copy the code
  • Class property binding

    / / 1, [. Class foo] = "hasFoo" : bool | undefined | null
    public hasFoo = true;
    
    // 2, [class]="classExpr" : string
    public classExpr = "my-class1 my-class2";
    
    // 3, [class]="classExpr" : {key:value}
    public classExpr= {my-class1:  true, my-class2: true};
    
    // 4, [class]="classExpr" : array
    public classExpr= ["my-class1"."my-class2"];
    Copy the code
event

In the event binding, you can retrieve template information by retrieving attributes of the DOM event object with the $event parameter

<input type="text" (keyup) ="getMsg($event)">
<p>Input values: {{MSG}}</p>
Copy the code
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {

  public msg: string;
  
  constructor() { }

  ngOnInit(): void {
  }

  getMsg(event: KeyboardEvent) {
    console.log(event);
    this.msg = (event.target asHTMLInputElement).value; }}Copy the code

By using the $event as a method of parameter will can’t use many template information is passed to the component, cause we’re just to get data under the premise of need for page elements very understanding, has violated the template (the user can see) and component (application) how to handle user data between the principles of classification of concerns. Therefore, data information should be obtained by using template reference variables.

A template reference variable is a reference to a DOM element in a template, providing the ability to access the element directly from the module.

<input type="text" #refMsgInput (keyup) ="getRefMsg(refMsgInput.value)">
<p>{{refMsg}}</p>
Copy the code
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-product-list',
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {

  public refMsg: string;

  constructor() { }

  ngOnInit(): void {
  }

  getRefMes(msg: string) {
    this.refMsg = msg; }}Copy the code

Template reference variables are scoped across the template, so make sure that reference variable names in a template are unique, and use ref- instead of # when declaring reference variables

<input type="text" ref-refMsgInput (keyup) ="getRefMsg(refMsgInput.value)">
<p>{{refMsg}}</p>
Copy the code

instruction

Attribute instruction

Attribute directives are applied to view DOM elements to change the appearance or behavior of the DOM element

  • NgClass: Used to set multiple CSS class attributes for an element. If only one CSS class is set, use the class binding in the template binding syntax

    <p [ngClass] ="inlineStyle">The NgClass property directive</p>
    Copy the code
    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-product-list',
      templateUrl: './product-list.component.html',
      styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {
    
      public inlineStyle: {};
    
      constructor() { }
    
      ngOnInit(): void {
        this.setInlineStyle();
      }
    
      setInlineStyle() {
        this.inlineStyle = {
          'text-red': true.'bg-blue': false}; }}Copy the code

    Text-red and bg-blue are CSS class names. If you want to add the class to the specified element, the CSS class name will be true, otherwise it will be false

  • NgStyle: Used to set multiple inline styles for elements. If you set only one inline style, use the style binding in the template binding syntax

    <p [ngStyle] ="currentStyles">NgStyle property directive</p>
    Copy the code
    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-product-list',
      templateUrl: './product-list.component.html',
      styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {
    
      public currentStyles: {};
    
      constructor() { }
    
      ngOnInit(): void {
        this.setCurrentStyles();
      }
    
      setCurrentStyles() {
        this.currentStyles = {
          'font-style': 'italic'.'font-weight': 'bold'.'font-size': '24px'}; }}Copy the code

    Batch setting of page element styles takes the form of multiple inline style objects in component properties

  • NgModel: Two-way data binding

    <input type="text" id="userName" [(ngModel)]="name">
    Copy the code

Structural instruction

Structural directives are used to manipulate the DOM tree and make logical decisions to modify the page layout

  • NgIf: Creates or destroys DOM elements based on the expression’s value (true or false)

    <p *ngIf="expr">NgIf structural instruction</p>
    Copy the code

    When the expr attribute is true, the element is displayed on the page. When the attribute value is false, the element is not displayed

    The ngIf directive does not hide elements by using CSS styles. When false, the elements are destroyed from the DOM, all events that listen to the DOM element are cancelled, and the initialization process is re-performed when the element is displayed

    Unlike destroying elements, for hidden elements, all element listening events are also listened on, and no reinitialization is required when displayed again

  • NgFor: Defines the display format of a single piece of data, which Angular uses as a template to loop through all data

    <p *ngFor="let item of products; let i = index">{{i+1}} - {{item.name}} --- {{item.price}}</p>
    Copy the code
    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-product-list',
      templateUrl: './product-list.component.html',
      styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {
    
      public products = [{
        'name': 'lalala'.'price': '$200'
      }, {
        'name': 'hehehe'.'price': '$400'
      }, {
        'name': 'wuwuwu'.'price': '$120'
      }, {
        'name': 'xixi'.'price': '$570'
      }];
    
      constructor() { }
    
      ngOnInit(): void{}}Copy the code

    The index property in the context of the NgFor directive gets the index value of the item in each iteration

    When the rendered data is changed [4], dom elements will be re-rendered. At this point, trackBy can be adopted to add a method in the component to specify the attribute value that the loop needs to track. At this point, when the rendered data is changed, only the data with the specified attribute value will be re-rendered

    <p>Do not use the trackBy tracking property</p>
    <div>
      <p *ngFor="let item of products; let i = index;">
        {{i+1}} - {{item.name}} --- {{item.price}}
      </p>
    </div>
    <p>Use trackBy to track properties</p>
    <div>
      <p *ngFor="let item of products; let i = index; trackBy: trackByIndex">
        {{i+1}} - {{item.name}} --- {{item.price}}
      </p>
    </div>
    <button (click) ="addProduct()">new</button>
    Copy the code
    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-product-list',
      templateUrl: './product-list.component.html',
      styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {
    
      public products = [{
        'name': 'lalala'.'price': '$200'
      }, {
        'name': 'hehehe'.'price': '$400'
      }, {
        'name': 'wuwuwu'.'price': '$120'
      }, {
        'name': 'xixi'.'price': '$570'
      }];
    
      constructor() { }
    
      ngOnInit(): void {
      }
    
      trackByIndex(index: number, item: any) :string {
        return item.price;
      }
    
      addProduct() {
        this.products = [{
          'name': 'lalala'.'price': '$200'
        }, {
          'name': 'hehehe'.'price': '$400'
        }, {
          'name': 'wuwuwu'.'price': '$120'
        }, {
          'name': 'xixi'.'price': '$570'
        }, {
          'name': 'lululu'.'price': '$' + (Math.random() * 100).toFixed() }]; }}Copy the code

  • NgSwitch: Based on the conditional switch, select the matching element from several candidates and place it in the DOM element

    <p>Please select configuration<select [(ngModel)] ="config">
        <option value="">Please select a</option>
        <option value="r7-3700x">AMD Ryzen 7 3700X</option>
        <option value="i5-9400f">Intel i5 9400F</option>
        <option value="i5-9600kf">Intel i5 9600KF</option>
      </select>
    </p>
    <p>Configuration description</p>
    <div [ngSwitch] ="config">
      <p *ngSwitchCase="'r7-3700x'">Someone who can beat the crap out of me</p>
      <p *ngSwitchCase="'i5-9400f'">Squeezed toothpaste...</p>
      <p *ngSwitchCase="'i5-9600kf'">Stop looking, I'm not kaifeng...</p>
      <p *ngSwitchDefault>You pick one</p>
    </div>
    Copy the code
    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-product-list',
      templateUrl: './product-list.component.html',
      styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {
    
      public config = ' ';
    
      constructor() { }
    
      ngOnInit(): void{}}Copy the code

    The NgSwitch itself is an attribute directive that does not operate directly on DOM elements. Instead, it operates on DOM elements through two structural directives it controls (NgSwitchCase and ngSwitchDefault)

The pipe

When using template expressions to bind data, you can use pipes to transform the result of the expression

Pipes are simple functions that take input values and return converted values. Through the template expressions used in the pipeline operator (|) can make the corresponding results of conversion

Special operators in template expressions

Angular template expressions are subsets of javascript, with three special operators added to common javascript operators

  • Pipe operator

    Pipe is a kind of special function, can put the operator (|) to the left of the data into expected to view the data format, for example, the time format, will be in the form of data into a json string, and so on

    Multiple pipes can be concatenated for a single data, and the pipe operators have a higher precedence than the ternary operators (? 🙂

    <h3>5.1. Pipe operators</h3>
    <div>
      <p>Product information JSON character string</p>
      {{products | json}}
    </div>
    Copy the code

  • Safe navigation operator

    When the property value used in a view is null or undefined, javascript and Angular raise a null pointer exception and interrupt the view’s rendering process, so that the view fails to render and uses the safe navigation operator instead. After that, the view is still rendered, but the values displayed are blank

    <h3>5.2 Safe navigation operator</h3>
    <p>The fifth project is named {{products[5].name}}</p>
    Copy the code

    <p>The fifth project is named {{products[5]? .name}}</p>
    Copy the code

  • Non-null assertion operator

    When strictNullChecks is enabled in tsconfig.json, typescript enforces strict null-checking. In this mode, attributes of defined types are not allowed to be assigned to null values

    The non-null assertion operator is used to tell the compiler not to strictly null-check a particular attribute, and not to throw errors when the attribute value is null or undefined. In the following code, obj.name is no longer validated after obj is determined to exist

    import { Component, OnInit } from '@angular/core';
    
    interface Person {
        name: string;
        age: number;
      }
    
      @Component({
        selector: 'app-product-list',
        templateUrl: './product-list.component.html',
        styleUrls: ['./product-list.component.scss']})export class ProductListComponent implements OnInit {
    
        public obj: Person;     
          
        constructor() {
        }
          
        ngOnInit(): void{}}Copy the code
    <p *ngIf="obj">
      <span>{{obj! .name}}</span>
    </p>
    Copy the code

    Non-empty assertion operators do not prevent null or undefined, they just do not prompt

Common pipe functions
  • Pure pipeline

    It only executes if it detects a pure change in the input value, but ignores changes inside the object

    Pure changes are changes to primitive type values (String, Number, Boolean, Symbol) or changes to Object references (Date, Array, Function, Object)

  • The pure pipeline

    Each component’s change cycle is executed

The pipe role
JsonPipe Converts a value to a JSON string
DatePipe Format date values according to locale rules
UpperCasePipe Convert the text to full uppercase
LowerCasePipe Convert text to full lowercase
<h3>6.1. Json Pipes</h3>
<p>{{products | json}}</p>

<h3>6.2. Date Pipeline</h3>
<p>Now time: {{date | date: 'MM - dd yyyy - HH: MM: ss'}}</p>

<h3>6.3. Upper Pipe</h3>
<p>Convert perfecting capital: {{url | uppercase}}</p>

<h3>6.4. Lower Pipeline</h3>
<p>Conversion fulfill lowercase: {{url | lowercase}}</p>
Copy the code

Communication between components

Input properties and output properties

Input attributes (@input) and Output attributes (@output) are used to share data between parent components or directives. @Input is used to fetch data, @Output is used to send data out

Child component gets information about the parent component
  • In the parent component, add a reference to the child component and bind the data or method that needs to be passed to the child component

    Passing data Directly assigns property values from the parent component to properties bound to the child component

    When passing a method, the property bound to the child component is the name of the parent component’s method. You cannot add () here, otherwise the parent component’s method will be executed directly

    When passing data to the child, you can also refer to the parent by this, thus binding the entire parent to the child

    <h2>Parent component contents:</h2>
    
    <p>
      <label for="title">Title:</label>
      <input id="title" type="text" [(ngModel)] ="title">
    </p>
    
    <hr>
    
    <h2>Sub-component content:</h2>
    
    <! Bind parent component data to child component -->
    <app-child-component [parentTitle] ="title" [parentGetMsg] ='getMsg'></app-child-component>
    Copy the code

  • Introduce Inupt in the child component and use the @INPUT decorator to receive data passed by the parent component

    // Introduce the Input interface
    import { Component, OnInit, Input } from '@angular/core';
    
    @Component({
      selector: 'app-child-component',
      templateUrl: './child-component.component.html',
      styleUrls: ['./child-component.component.scss']})export class ChildComponentComponent implements OnInit {
    
      // Get the data of the parent component
      @Input() parentGetMsg: any;
    
      // Use setters to further process the parent component's data
      private _title: string;
      @Input(a)set parentTitle(title: string) {
        this._title = (title && title.trim()) || 'Parent component's title property value is null';
      }
      get parentTitle(): string {
        return this._title;
      }
    
      constructor() { }
    
      ngOnInit(): void {
      }
    
      runParentFunc() {
        this.parentGetMsg(); }}Copy the code
    <p>Parent component title property value: {{parentTitle}}</p>
    <p>
      <button (click) ="runParentFunc()">Call the parent component's method</button>
    </p>
    Copy the code

    Parent component data obtained using the @INPUT decorator can be reassigned through setter methods in Input properties

The parent component gets the child component information
  • Get it using the @viewChild decorator

    Define a template reference variable on the child component

    <h2>Parent component contents:</h2>
    
    <h3>1. Use the @viewChild decorator to get child component data</h3>
    
    <p>
      <button (click) ="getChildMsg()">Gets the MSG data for the child component</button>
    </p>
    
    <p>
      <button (click) ="runChildFunc()">Invoke methods of child components</button>
    </p>
    
    <hr>
    
    <h2>Sub-component content:</h2>
    
    <! Define a template reference variable on the child component -->
    <app-child-component #childComponent></app-child-component>
    Copy the code

    Add a reference to the ViewChild in the parent component, and then use the @ViewChild decorator to receive the child’s DOM information to get the child’s data or methods

    / / introduce ViewChild
    import { Component, OnInit, ViewChild } from '@angular/core';
    
    @Component({
      selector: 'app-parent-component',
      templateUrl: './parent-component.component.html',
      styleUrls: ['./parent-component.component.scss']})export class ParentComponentComponent implements OnInit {
    
      // Receive the word component's DOM information via the @viewChild decorator
      @ViewChild('childComponent') child: any;
    
      constructor() {
      }
    
      ngOnInit(): void {
      }
    
      getMsg() {
        alert('I'm the parent component's getMsg method');
      }
    
      getChildMsg() {
        alert(this.child.msg); }}Copy the code

  • Implemented with the @Output decorator in conjunction with EventEmitter

    Add Output and EventEmitter to the child component, define an event trigger with the @Output decorator, and broadcast events through the emit method of this event trigger

    // Add Output, EventEmitter
    import { Component, OnInit, Output, EventEmitter } from '@angular/core';
    
    @Component({
      selector: 'app-child-component',
      templateUrl: './child-component.component.html',
      styleUrls: ['./child-component.component.scss']})export class ChildComponentComponent implements OnInit {
    
      public msg = 'child title';
    
      // Define an event trigger
      @Output() childEmitter = new EventEmitter<string> ();constructor() { }
    
      ngOnInit(): void {
      }
    
      runParentFunc() {
        this.parentGetMsg();
      }
    
      sendMsg() {
        this.childEmitter.emit(this.msg); }}Copy the code

    When a child component broadcasts an event, it can be bound to a parent component event by using event bindings on the child component to get the data value passed by the child component through $event

    <h2>Parent component contents:</h2>
    
    <h3>2. Use the @Output decorator and EventEmitter to get sub-component data</h3>
    
    <p>{{childMsg}}</p>
    
    <hr>
    
    <h2>Sub-component content:</h2>
    
    <! Bind the event broadcast of the child to the event of the parent.
    <app-child-component (childEmitter) ='childEmitMsg($event)'></app-child-component>
    Copy the code
    import { Component, OnInit } from '@angular/core';
    
    @Component({
      selector: 'app-parent-component',
      templateUrl: './parent-component.component.html',
      styleUrls: ['./parent-component.component.scss']})export class ParentComponentComponent implements OnInit {
    
      public childMsg: string;
    
      constructor() {
      }
    
      ngOnInit(): void {
      }
    
      childEmitMsg(event) {
        this.childMsg = event; }}Copy the code

Communication between non-parent and child components

Regardless of whether components are associated with each other, they can share a service to interact with each other. They can also store the data to be shared in some storage media and communicate with each other by reading the data in the storage media

  • Create a service and add it to the module

    #Create a storage service under services/storage
    ng g service services/storage/storage
    Copy the code
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppRoutingModule } from './app-routing.module';
    import { AppComponent } from './app.component';
    import { ProductListComponent } from './product-list/product-list.component';
    import { FormsModule } from '@angular/forms';
    import { ParentComponentComponent } from './parent-component/parent-component.component';
    import { ChildComponentComponent } from './child-component/child-component.component';
    
    // Introduce a custom service
    import { StorageService } from './services/storage/storage.service';
    
    @NgModule({
      declarations: [
        AppComponent,
        ProductListComponent,
        ParentComponentComponent,
        ChildComponentComponent
      ],
      imports: [
        BrowserModule,
        AppRoutingModule,
        FormsModule
      ],
      // Configure a user-defined service
      providers: [StorageService],
      bootstrap: [AppComponent]
    })
    
    export class AppModule { }
    Copy the code

  • Use services in components

    The use of the service in the component can be accomplished by importing the service into the component that needs to be used and then injecting the service in the constructor of the component through dependency injection

    Assign values to the data in the parent component, and then call the service’s methods to change the data information

    import { Component, OnInit } from '@angular/core';
    
    // Import services
    import { StorageService } from '.. /services/storage/storage.service';
    
    @Component({
      selector: 'app-parent-component',
      templateUrl: './parent-component.component.html',
      styleUrls: ['./parent-component.component.scss']})export class ParentComponentComponent implements OnInit {
    
      public msg = 'this is a service default value writen in parent component';
    
      constructor(private storage: StorageService) {
        this.storage.setMsg(this.msg);
      }
    
      ngOnInit(): void {
      }
    
      submit() {
        this.storage.setMsg(this.msg); }}Copy the code
    <h2>Parent component contents:</h2>
    
    <h3>3. Share data in properties through services</h3>
    
    <p>Modify data values in the service<input type="text" [(ngModel)] ="msg">
      <button (click) ="submit()">submit</button>
    </p>
    
    <p>Data in service: {{MSG}}</p>
    
    <hr>
    
    <h2>Sub-component content:</h2>
    
    <app-child-component></app-child-component>
    Copy the code

    Services are introduced into the child component to synchronize data information from the modified service of the parent component

    import { Component, OnInit } from '@angular/core';
    
    // Import services
    import { StorageService } from '.. /services/storage/storage.service';
    
    @Component({
      selector: 'app-child-component',
      templateUrl: './child-component.component.html',
      styleUrls: ['./child-component.component.scss']})export class ChildComponentComponent implements OnInit {
    
      public storageMsg: string;
    
      constructor(private storage: StorageService) {
      }
    
      ngOnInit(): void {
      }
    
      getServiceMsg() {
        this.storageMsg = this.storage.getMsg(); }}Copy the code
    <button (click) ="getServiceMsg()">Gets the data values in the service</button>
    <p>MSG attribute value in service: {{storageMsg}}</p>
    Copy the code

A component’s lifecycle hook function

Angular intervenes in critical moments by implementing component lifecycle hook functions that trigger when a component is created, updated, or destroyed

Hook function trigger
ngOnChanges When the value of the bound input property changes, it will be called multiple times; Does not fire if parent component pass is not used
ngOnInit Called once when a component is initialized, typically to perform its complex initialization logic after a constructor
ngDoCheck It is called whenever the data changes
ngAfterContentInit Called once component content has been rendered
ngAfterContentChecked It is called whenever the content of the component changes
ngAfterViewInit Once the view is loaded, it is used to manipulate the DOM elements of the view
ngAfterViewChecked Called when the view changes, and many times over the life of the component
ngOnDestroy Called only once when a component is destroyed, usually to perform some action before the component is destroyed

During the component loading process, the hook functions listed above are executed after the constructor of the component. During the page loading process, the data binding operation is involved. The three lifecycle hook functions, ngDoCheck, ngAfterContentChecked, and ngAfterViewChecked, are invoked again. Subsequent changes to page data will trigger these events

Of the pit

Personal Profile: Born in 1996, born in a fourth-tier city in Anhui province, graduated from Top 10 million universities. .NET programmer, gunslinger, cat. It will begin in December 2016. NET programmer career, Microsoft. NET technology stalwart, aspired to be the cloud cat kid programming for Google the best. NET programmer. Personal blog: yuiter.com blog garden blog: www.cnblogs.com/danvic712


  1. A decorator is a special type of declaration that can be attached to a class declaration, method, accessor, property, or parameter, just like the C# feature ↩︎

  2. Metadata is a data item used to describe data. For example, selector here is a structured data extracted from the data information resource to describe Component, which is used to describe its characteristics ↩︎

  3. Property is the default basic attribute of A DOM element and is created during DOM initialization. Attribute is an attribute and value defined on an HTML tag = The difference between property and attribute in DOM ↩︎

  4. Data changes here refer to the process of re-destroying and rebuilding the original data objects, so methods like Push and unshift do not re-render the entire DOM without adding trackBy, only the changed data ↩︎