Attributes, element operations, and directives Common data image display template reference variables NgForNgSwitch and NgIfNgClass and NgStyle pipe safety navigation operators (‘? ‘) and empty attribute path binding syntax Bind type and Bind target event Common Click event Form event Bidirectional data binding $Event and event handling statement Form Form search TodoList

Attributes, element operations, and directives

Common data

To create a new news component, first define variables in the news.component.ts file:

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



@Component({

  selector: 'app-news'.

  templateUrl: './news.component.html'.

  styleUrls: ['./news.component.css']

})

export class NewsComponent implements OnInit {



  title = 'Hello hresh';



  public name: any = 'hresh';



  content: any = '<h3>Hello Java</h3>';



  msg = 'Hello China';



  constructor() {

    this.msg = 'Hello China';



  }



  ngOnInit(): void {

  }



}

Copy the code

Define tags in HTML files to get defined variables and display:

<div>

  <p>news works!</p>

    <! -- Data text binding -->

  <h3>{{title}}</h3>



  <hr />

  <h1>{{content}}</h1>



  <br>

    <! - binding HTML - >

  <span [innerHTML] ="content"></span>



  <br>

  <h2>{{msg}}</h2>



  <br>



1 + 1 + 1 = {{1}}

</div>

Copy the code

The renderings are as follows:

Pictures show

Image resources can be obtained locally or from the Internet. Perform the following configuration in the HTML file:

  <h3>Introduction of pictures</h3>



  <img src="assets/images/10001.png" alt="hello" />



  <hr>

  <img [src] ="picUrl" />

  <img src="{{picUrl}}" />

Copy the code

Local static resources are stored in the following locations:

Links to online image resources can be defined in argular01.component.ts:

public picUrl = 'https://cn.bing.com/th?id=OIP.bbd7bi181qua_NdZzguE3QHaE6&pid=Api&rs=1';

Copy the code

The webpage display is as follows:

Template reference variable

A template reference variable is usually a reference to a DOM element in a template. It can also reference directives (containing components), elements, TemplateRef, or Web Components.

Declare template reference variables using a pound sign (#). The following template reference variable #phone declares a phone variable on the input element.

<input #phone placeholder="phone number" />



<! -- lots of other elements -->



<! -- phone refers to the input element; pass its `value` to an event handler -->

<button (click) ="callPhone(phone.value)">Call</button>

Copy the code

The scope of a template reference variable is the entire template. Therefore, do not define the same variable name multiple times in the same template, because its value at run time will be unpredictable.

Alternative syntax

You can also use the ref- prefix instead of #. In the following example, we declare the fax variable ref-fax instead of #fax.

<input ref-fax placeholder="fax number" />

<button (click) ="callFax(fax.value)">Fax</button>

Copy the code

NgFor

The ngFor directive iterates through the array of items returned by the items property of the parent component and sets item to the current item in that array during each iteration. The index attribute in the context of the NgFor directive returns the zero-based index of the item in each iteration. You can capture index in the template input variable and use it in the template.

Also in the news component, first define the contents of the array:

nums: any[] = [111.2222.333];

public values: Array<string> = ['111'.'222'.'333'];



userList: any[] = [

    {

        name : 'hresh'.

        age : 22

    },

    {

        name : 'hresh2'.

        age : 22

    },

    {

        name : 'hresh3'.

        age : 22

    }

]



cars: any[] = [

    {

        name'BMW'.

        list: [

            {

                title'x1'.

                price'300000'

            },

            {

                title'x2'.

                price'300000'

            },

            {

                title'x3'.

                price'300000'

            }

        ]

    },

    {

        name'Mercedes'.

        list: [

            {

                title'x1'.

                price'300000'

            },

            {

                title'x2'.

                price'300000'

            },

            {

                title'x3'.

                price'300000'

            }

        ]

    }

]

Copy the code

Add content to an HTML file:

  <ul>

    <li *ngFor="let item of nums">

      {{item}}

    </li>

  </ul>



  <br>



  <ul>

    <li *ngFor="let item of userList">

      {{item.name}}---{{item.age}}

    </li>

  </ul>



  <br>

  <ul>

    <li *ngFor="let item of cars">

      {{item.name}}

      <ul>

        <li *ngFor="let car of item.list">

          {{car.title}}----{{car.price}}

        </li>

      </ul>

    </li>

  </ul>

Copy the code

The effect is as follows:

* ngFor with trackBy

Here’s an example:

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



@Component({

 selector'trackBy-test'.

 template`

<ul><li *ngFor="let item of items; >{{item.name}}</li></ul>

 <button (click)="getItems()">Get Items</button>

 `


})

export class TrackByCmp{

 items: any[]=[];

 constructor() {

  this.items = [{id:'1'.name:'Tom'}, {id:'2'.name:'Jerry'}, {id:'3'.name:'Kitty'}];

 }

 getItems(){

  this.items = [{id:'1'.name:'Tom'}, {id:'2'.name:'Jerry'}, {id:'4'.name:'Mac'}, {id:'5'.name:'John'}];

 }

}

Copy the code

Sometimes you will need to change this collection, such as when new data is returned from the back-end interface. The problem is that Angular doesn’t know how to keep track of items in the collection, which ones to add, which ones to modify and which ones to remove. As a result, Angular removes all items from the collection and adds them back in. Something like this:

The downside of this is that you do a lot of DOM manipulation, and DOM manipulation is very performance intensive.

The solution is to add a trackBy function to *ngFor that tells Angular how to track items in the collection. The trackBy function takes two arguments, the first is the index of the current item and the second is the current item, and returns a unique identifier, like this:

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



@Component({

 selector'trackBy-test'.

 template`

<ul><li *ngFor="let item of items; trackBy: trackByIndex">{{item.name}}</li></ul>

 <button (click)="getItems()">Get Items</button>

 `


})

export class TrackByCmp{

 items: any[]=[];

 constructor() {

  this.items = [{id:'1'.name:'Tom'}, {id:'2'.name:'Jerry'}, {id:'3'.name:'Kitty'}];

 }

 getItems(){

  this.items = [{id:'1'.name:'Tom'}, {id:'2'.name:'Jerry'}, {id:'4'.name:'Mac'}, {id:'5'.name:'John'}];

 }

trackByIndex(index, item){

  return index;

 }

}

Copy the code

Angular knows which items have changed after you change them:

For more on trackBy, see: Angular- Use NgForOf’s trackBy to improve performance

NgSwitch and NgIf

You first need to define the relevant data content in argular01.com component.ts:

nums: any[] = [111.222.333];



flag = false;



order = 1;

Copy the code

The content of the HTML file is as follows:

  <h3>Loop to display the index of the data</h3>

  <div>

    <ul>

      <li *ngFor="let item of nums; let key =index">

        <span *ngIf="key == 1" class="red">{{key+1}}----{{item}}</span>

        <span *ngIf="key ! = 1">{{key+1}}----{{item}}</span>

      </li>

    </ul>

  </div>





  <br>

  <h3>judge</h3>



  <div *ngIf="flag">

    <p>I'm a P tag</p>

  </div>

  <div *ngIf=! "" flag">

    <p>I am a PP tag</p>

  </div>

  <br>



  <h3>NgSwitch</h3>

  <span [ngSwitch] ="order">

    <p *ngSwitchCase="1">

      1111111111

    </p>

    <p *ngSwitchCase="2">

      2222222222222

    </p>

    <p *ngSwitchDefault>

      00000000000

    </p>

  </span>

Copy the code

In addition to the usage of ngIf and ngSwitch, this article also introduces the definition of circular indexes (indexes start at 0), which are used in conjunction with ngIf.

The webpage rendering is as follows:

NgClass and NgStyle

Use ngClass to add or remove several CSS classes simultaneously.

<div>

  <div [ngClass] ="currentClasses">This div is initially saveable, unchanged, and special.</div>



  <div [ngClass] ="isSpecial ? 'special' : ''">This div is special</div>

  <div [class] ="isSpecial ? 'special2' : ''">This div is special</div>

</div>

Copy the code

Consider a setCurrentClasses() component method that sets a component property currentClasses, which has an object that adds or removes three CSS classes based on the true/false status of the other three component properties. Each key of this object is a CSS class name. The value is true if the class is to be added, false otherwise.

home2.component.ts

  canSave = true;

  isUnchanged = true;

  isSpecial = true;

  constructor() {}



  ngOnInit(): void {

    this.setCurrentClasses();

  }



  setCurrentClasses() {

    this.currentClasses = {

      'saveable'this.canSave,

      'modified':!this.isUnchanged,

      'special'this.isSpecial

    };

  }

Copy the code

CSS styles:

.saveable{

  background-color: blue;

}

.modified{

  font-size21px;

}



.special{

  font-weight200;

}



.special2{

  font-weight200;

}

Copy the code

Page test:

As you can see from the example above, using class binding is consistent with Ngclass effects when adding a single class. So the official documentation recommends that to add or remove individual classes, use class bindings instead of ngClasses.

Use NgStyle to dynamically set multiple inline styles simultaneously based on the state of the component.

  <div [ngStyle] ="currentStyles">

    This div is initially italic, normal weight, and extra large (24px).

  </div>



  <div [style.font-size] ="isSpecial ? 'x-large' : 'smaller'">

    This div is x-large or smaller.

  </div>

Copy the code

The following example is a setCurrentStyles() method that sets the currentStyles property with an object that defines three styles based on the state of the component’s other three properties.

  currentStyles: any = {};



  canSave = true;

  isUnchanged = true;

  isSpecial = true;

  constructor() {}



  ngOnInit(): void {

    this.setCurrentStyles();

  }



  setCurrentStyles() {

    // CSS styles: set per current state of component properties

    this.currentStyles = {

      'font-style'this.canSave ? 'italic' : 'normal'.

      'font-weight':!this.isUnchanged ? 'bold' : 'normal'.

      'font-size'this.isSpecial ? '24px' : '12px'

    };

  }

Copy the code

Page test:

As with ngClass, the official documentation also recommends style binding for a single style value, using the NgStyle directive to set multiple inline styles.

The pipe

Pipes are a good way to format strings, amounts, dates, and other display data

Angular comes with many Pipes, such as the Date pipe and currency pipe. See the Pipes API list for a complete list. You can also define some new pipes yourself.

Set the value in the birthday.component.ts file as follows:

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



@Component({

  selector'app-birthday'.

  templateUrl'

    <p>The hero'
s birthday is {{ birthday | date:format }}</p>

    <button (click)="toggleFormat()">Toggle Format</
button>

  '

})

export class BirthdayComponent implements OnInit {



  birthday = new Date(1988, 3, 15); // April 15, 1988

  toggle = true; // start with true == shortDate



  constructor() { }



  ngOnInit(): void {

  }



  get format()   { return this.toggle ? '
shortDate':'fullDate'; }

toggleFormat() { this.toggle = ! this.toggle; }

}

Copy the code

Webpage display effect:

The safe navigation operator (‘? ‘) and the empty property path

Angular secure navigation operator? You can protect against null and undefined values appearing in property paths. In this case, if item is null, it prevents view rendering from failing.

<p>The item name is: {{item? .name}}</p>

Copy the code

If item is null, the view is still rendered, but the value displayed is blank; You’ll just see “The item name is:” with nothing after it.

Consider the following example with nullItem.

The null item name is {{nullItem.name}}

Copy the code

Because there is no safe navigation operator and nullItem is null, JavaScript and Angular raise nullpointer errors and interrupt Angular rendering:

content_copyTypeError: Cannot read property 'name' of null.

Copy the code

However, there are times when a null value in a property path may be acceptable, especially if the value starts out empty but the data eventually arrives.

Use safe navigation operators? When an Angular expression hits the first null value, it stops evaluating the expression and renders an error-free view.

Binding syntax

Data binding is a mechanism for coordinating what is visible to the user, especially the value of application data. While you can push or pull these values from the HTML manually, the application is much easier to write, read, and maintain if you delegate these tasks to the binding framework. All you have to do is declare a binding relationship between the data source and the target HTML element, and the framework does the rest.

Angular provides multiple ways to bind data. Binding types can be divided into three categories according to the direction of the data flow:

  • fromData source to view
  • fromView to data Source
  • Two-way:View to data source to view

Binding type and binding target

Data binding targets objects in the DOM. Depending on the binding type, the target can be a Property name (of an element, component, or directive), an event name (of an element, component, or directive), and sometimes an Attribute name. The goals for the different binding types are summarized in the following table. This section will be illustrated with examples. There is no fixed space for this section. See Angular Module Syntax for details

The event

Normal click events

First modify the HTML file:

<h3>The event</h3>

<button (click) ="run()">Perform event</button>

<br>

<br>

<button (click) ="getData()">To get the data</button>

<br>

<br>

<strong>{{title}}</strong>

<br>

<br>

<button (click) ="setData()">Set up the data</button>

<br>

<br>

<button (click) ="runEvent($event)" id="btn">Execute the method to get the event object</button>

<br>

Copy the code

Then add the implementation method in the argular01.component.ts file

  title = 'It's a theme.';



  keywords = 'This is an input'



  run() {

    alert('hello');

  }

  constructor() {}



  ngOnInit(): void {

  }



  getData() {

    alert(this.title);

  }

  setData() {

    this.title = 'New Theme';

  }

  runEvent(e) {

    var dom = e.target;

    dom.style.color = 'red';

  }

Copy the code

The webpage display effect is as follows:

Form events

HTML file:

<h3>Form event event object</h3>

<! --<input type="text" (keydown)="keydown()">-->

<br>

<input type="text" (keydown) ="keydown($event)">

<br>

<input type="text" (keyup) ="keyup($event)" >

Copy the code

Then add the implementation method in the argular01.component.ts file

  keydown(e) {

    console.log(e.target.value);

  }

  keyup(e) {

    if (e.keyCode == 13) {

      console.log('Hit enter');

    }

  }

Copy the code

The webpage display effect is as follows:

In addition to the example of statement and event binding, the statement context can reference properties in the template’s own context, passing the template’s $event object to the component’s event handler in the above example, and passing template input variables (let key) and template reference variables (#inputDom) to component methods.

    <input type="text" #inputDom (input) ="getData2(inputDom.value)" />

    <br>

    <div>

      <ul>

        <li *ngFor="let item of nums; let key =index">

          <span>{{key+1}}----{{item}}</span>&nbsp;

          <button (click) ="delete(key)">X</button>

        </li>

      </ul>

    </div>

Copy the code

The event method is defined as follows:

  getData2(data: any) {

    console.log(data);

  }



  delete(key) {

    this.nums.splice(key, 1);

  }

Copy the code

Page test:

Two-way data binding

Bidirectional binding does two things:

  1. Sets specific element attributes.

  2. Listen for changes to elements.

    Angular provides a special two-way data binding syntax [()] for this purpose. The [()] syntax combines the property-bound parentheses [] with the event-bound parentheses ().

First introduce the NgModule in app.module.ts and declare it.

// Browser parsing module

import { BrowserModule } from '@angular/platform-browser';

// Angular core modules

import { NgModule } from '@angular/core';

import {FormsModule} from '@angular/forms';



/ / the root component

.



// @NgModule decorator. @NgModule takes a metadata object that tells Angular how to compile and launch an application

@NgModule({

  declarations: [// Configure the component that the current project runs on

    AppComponent, NewsComponent, Argular01Component, FormComponent, SearchComponent

].

  imports: [// Configure other modules on which the current module depends

    BrowserModule,

    FormsModule

].

  providers: [StorageService],

  bootstrap: [AppComponent]

})

export class AppModule {}

Copy the code

HTML file contents:

    <h3>Two-way binding</h3>

    <p><input type="text" [(ngModel)] ="keywords"></p>



    <span>{{keywords}}</span>

    <br>

    <br>

    <span><button (click) ="upkeywords()">Modify the data</button></span>

Copy the code

Finally, define variables and methods in argular01.component.ts.

keywords = 'This is an input';



upkeywords() {

    this.keywords = 'Changed data';

}

Copy the code

Webpage display effect:

(Input)=”getData2(inputdom.value)” (input)=”getData2(inputDom.value)”

$eventAnd event handling statements

HTML file:

<p>Input data binding:<input [value] ="keywords"

                    (input) ="keywords=$event.target.value" >
</p>

<span>{{keywords}}</span>

Copy the code

The above code binds the value property of the input field to the name property. To listen for changes to values, the code binds to the input event of the input box. When the user makes a change, the input event is fired and executed in a context containing the DOM event object ($event).

To update the name attribute, get the changed value from the path $event.target.value.

Page test:

Form Form

Create a new component:

ng g component components/form

Copy the code

First introduce the NgModule in app.module.ts and declare it.

1, form.com ponent. HTML

  <h2>Personnel registration system</h2>



  <! Input, checkbox, radio, select, textarea

  <div class="people_list">

    <ul>

      <li>

Name:

        <input type="text" [(ngModel)] ="peopleInfo.username" id="username" class="form_input">

      </li>





      <li>

Don't:

        <input type="radio" value="1" name="sex" id="man" [(ngModel)] ="peopleInfo.sex"> <label for="man">male</label>

        <input type="radio" value="2" name="sex" id="woman" [(ngModel)] ="peopleInfo.sex"> <label for="woman">female</label>

      </li>



      <li>

City:

        <select [(ngModel)] ="peopleInfo.city">

          <option *ngFor="let item of peopleInfo.cities">

            {{item}}

          </option>

        </select>

      </li>

      <li>

Love good:

        <span *ngFor="let item of peopleInfo.hobbies; let key=index" >

          <input type="checkbox" [id] ="'check'+key" [(ngModel)] ="item.checked"><label [for] ="'check'+key">{{item.title}}</label>

&nbsp; &nbsp;

        </span>

      </li>

      <li>

Case note:

        <textarea [(ngModel)] ="peopleInfo.remark" cols="30" rows="2"></textarea>

      </li>



      <br>

      <button (click) ="getData()">Gets the value of the form</button>



      <pre>

        {{peopleInfo | json}}

      </pre>

    </ul>

  </div>

Copy the code

2, form.com ponent. CSS

ul.ol{

  list-style-type: none;

}

* {

  margin0px;

  padding:0px;

}



h2{

  text-align: center;

}

.people_list{

  width400px;

  margin40px auto;



  padding20px;



  border1px solid #eeeeee;



}



.people_list li{

  height50px;



  line-height50px;

}



.form_input{

  width300px;

  height28px;

}

Copy the code

3, form.com ponent. Ts

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



@Component({

  selector'app-form'.

  templateUrl'./form.component.html'.

  styleUrls: ['./form.component.css']

})

export class FormComponent implements OnInit {



  peopleInfo: any = {

    username' '.

    sex'1'.

    cities: ['Beijing'.'Shanghai'.'shenzhen'].

    city'Shanghai'.

    hobbies: [

      {

        title'eat'.

        checkedfalse

      },

      {

        title'sleep'.

        checkedfalse

      },

      {

        title'Write code'.

        checkedtrue

      }

].

    remark' '

  }

  constructor() {}



  ngOnInit(): void {

  }



  getData() {

    console.log(this.peopleInfo);

  }

}

Copy the code

4. Webpage display effect

5, summary

For gender radio and hobby boxes, what changes happened to the front desk when they were checked, and what data were bound to two-way data.

Note the change in the ng-reflect-model value in the GIF above.

search

Create a new component:

ng g component components/search

Copy the code

First introduce the NgModule in app.module.ts and declare it.

1, search.com ponent. HTML

<h2>search</h2>



<div class="search">

  <input type="text" [(ngModel)] ="keyWord" (keyup) ="keyup($event)">&nbsp; &nbsp;<button (click) ="search()">search</button>



  <hr>

  <ul>

    <li  *ngFor="let item of keyWordsOld; let key=index"> {{item}} ----- <button (click) ="delete(key)">X</button></li>

  </ul>

</div>

Copy the code

2, search.com ponent. Ts

keyWord: any = ' ';



keyWordsOld: any[] = [];



keyup(e) {

    if (e.keyCode === 13) {

        if (this.keyWordsOld.indexOf(this.keyWord) === - 1) {

            this.keyWordsOld.push(this.keyWord);

        }

        this.keyWord = ' ';

    }

}



search() {

    if (this.keyWordsOld.indexOf(this.keyWord) == - 1) {

        this.keyWordsOld.push(this.keyWord);

    }

    this.keyWord = ' ';

}



delete(key) {

    this.keyWordsOld.splice(key, 1);

}

Copy the code

3. Webpage display effect

Combined with our daily habits of using Taobao and JD.com, search records will be retained, which involves data persistence, which will be integrated and explained later.

TodoList(Todos and Done items)

Practice two-way binding to switch between to-do and done items.

1, search.com ponent. HTML

<h2>Search todoList</h2>



<div class="search">

  <input type="text" [(ngModel)] ="product" (keyup) ="add($event)" >



  <hr>

todo

  <ul>

    <li *ngFor="let item of products; let key=index" [hidden] ="item.status == 1">

      <input type="checkbox" [(ngModel)] ="item.status">{{item.status}} ----  {{item.title}}

      ----- <button (click) ="deleteWay(key)">X</button>

    </li>

  </ul>

  <hr>

Already backlog items

  <ul>

    <li *ngFor="let item of products; let key=index" [hidden] ="item.status == 0">

      <input type="checkbox" [(ngModel)] ="item.status" >{{item.status}} ----  {{item.title}}

      ----- <button (click) ="deleteWay(key)">X</button>

    </li>

  </ul>

      <hr>

  <div>

    <pre>

      {{products | json}}

    </pre>

  </div>

</div>

Copy the code

2, search.com ponent. Ts

product: any = ' ';

products: any[] = [];



add(e) {

    // tslint:disable-next-line:triple-equals

    if (e.keyCode == 13) {

        if (!this.equalProduct(this.products, this.product)) {

            this.products.push({

                titlethis.product,

                status0

            });

            this.product = ' ';

        } else {

            alert('Data already exists');

            this.product = ' ';

        }

    }

}



deleteWay(key) {

    this.products.splice(key, 1);

}



equalProduct(products: any[], value: any) {



    if(! value || value ===' ') {

        return false;

    }



    // tslint:disable-next-line:prefer-for-of

    for (let i = 0; i < products.length; i++) {

        // tslint:disable-next-line:triple-equals

        if (products[i].title == value) {

            return true;

        }

    }

    return false;

}

Copy the code

3. Webpage display effect