Built-in directives
از directiveهای built-in در Angular برای مدیریت formها، listها، styleها و چیزهایی که کاربر میبیند استفاده کنید.
نوعهای مختلف directive در Angular به این شکلاند:
| Directive Types | Details |
|---|---|
| Components | همراه با template استفاده میشوند. این نوع directive رایجترین نوع directive است. |
| Attribute directives | ظاهر یا behavior یک element، component یا directive دیگر را تغییر میدهند. |
| Structural directives | با اضافه و حذف کردن DOM elementها، layout مربوط به DOM را تغییر میدهند. |
این راهنما attribute directiveهای built-in را پوشش میدهد.
Attribute directiveهای built-in
Attribute directiveها به behavior مربوط به elementهای HTML، attributeها، propertyها و componentهای دیگر گوش میدهند و آن را modify میکنند.
رایجترین attribute directiveها عبارتاند از:
| Common directives | Details |
|---|---|
NgClass | مجموعهای از CSS classها را اضافه و حذف میکند. |
NgStyle | مجموعهای از styleهای HTML را اضافه و حذف میکند. |
NgModel | two-way data binding را به یک HTML form element اضافه میکند. |
اضافه و حذف کردن classها با NgClass
با ngClass چند CSS class را همزمان اضافه یا حذف کنید.
Import کردن NgClass در component
برای استفاده از NgClass، آن را به list مربوط به imports در component اضافه کنید.
import {NgClass} from '@angular/common';
@Component({
/* ... */
imports: [NgClass],
})
export class AppComponent {}استفاده از NgClass با یک expression
روی elementی که میخواهید style دهید، [ngClass] را اضافه کنید و آن را برابر یک expression قرار دهید. در این حالت، isSpecial یک boolean است که در app.component.ts روی true تنظیم شده است. چون isSpecial برابر true است، ngClass کلاس special را روی <div> اعمال میکند.
<h1>Built-in Directives</h1>
<h2>Built-in attribute directives</h2>
<h3 id="ngModel">NgModel (two-way) Binding</h3>
<fieldset>
<h4>NgModel examples</h4>
<p>Current item name: {{ currentItem.name }}</p>
<p>
<label for="without">without NgModel:</label>
<input [value]="currentItem.name" (input)="currentItem.name = getValue($event)" id="without" />
</p>
<p>
<!-- #docregion NgModel-1 -->
<label for="example-ngModel">[(ngModel)]:</label>
<input [(ngModel)]="currentItem.name" id="example-ngModel" />
<!-- #enddocregion NgModel-1 -->
</p>
<p>
<label for="example-change">(ngModelChange)="...name=$event":</label>
<input
[ngModel]="currentItem.name"
(ngModelChange)="currentItem.name = $event"
id="example-change"
/>
</p>
<p>
<label for="example-uppercase"
>(ngModelChange)="setUppercaseName($event)"
<!-- #docregion uppercase -->
<input
[ngModel]="currentItem.name"
(ngModelChange)="setUppercaseName($event)"
id="example-uppercase"
/>
<!-- #enddocregion uppercase -->
</label>
</p>
</fieldset>
<hr />
<h2 id="ngClass">NgClass Binding</h2>
<p>currentClasses is {{ currentClasses | json }}</p>
<!-- #docregion NgClass-1 -->
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div>
<!-- #enddocregion NgClass-1 -->
<ul>
<li>
<label for="saveable">saveable</label>
<input type="checkbox" [(ngModel)]="canSave" id="saveable" />
</li>
<li>
<label for="modified">modified:</label>
<input
type="checkbox"
[value]="!isUnchanged"
(change)="isUnchanged = !isUnchanged"
id="modified"
/>
</li>
<li>
<label for="special"
>special: <input type="checkbox" [(ngModel)]="isSpecial" id="special"
/></label>
</li>
</ul>
<button type="button" (click)="setCurrentClasses()">Refresh currentClasses</button>
<div [ngClass]="currentClasses">
This div should be {{ canSave ? '' : 'not' }} saveable,
{{ isUnchanged ? 'unchanged' : 'modified' }} and {{ isSpecial ? '' : 'not' }} special after
clicking "Refresh".
</div>
<br /><br />
<!-- #docregion special-div -->
<!-- toggle the "special" class on/off with a property -->
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
<!-- #enddocregion special-div -->
<div class="helpful study course">Helpful study course</div>
<div [ngClass]="{'helpful': false, 'study': true, 'course': true}">Study course</div>
<!-- NgStyle binding -->
<hr />
<h3>NgStyle Binding</h3>
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'">This div is x-large or smaller.</div>
<h4>[ngStyle] binding to currentStyles - CSS property names</h4>
<p>currentStyles is {{ currentStyles | json }}</p>
<!-- #docregion NgStyle-2 -->
<div [ngStyle]="currentStyles">
This div is initially italic, normal weight, and extra large (24px).
</div>
<!-- #enddocregion NgStyle-2 -->
<br />
<label for="canSave">italic: <input id="canSave" type="checkbox" [(ngModel)]="canSave" /></label> |
<label for="isUnchanged"
>normal: <input id="isUnchanged" type="checkbox" [(ngModel)]="isUnchanged"
/></label>
|
<label for="isSpecial"
>xlarge: <input id="isSpecial" type="checkbox" [(ngModel)]="isSpecial"
/></label>
<button type="button" (click)="setCurrentStyles()">Refresh currentStyles</button>
<br /><br />
<div [ngStyle]="currentStyles">
This div should be {{ canSave ? 'italic' : 'plain' }},
{{ isUnchanged ? 'normal weight' : 'bold' }} and,
{{ isSpecial ? 'extra large' : 'normal size' }} after clicking "Refresh".
</div>
<hr />
<h2>Built-in structural directives</h2>
<h3 id="ngIf">NgIf Binding</h3>
<div>
<p>If isActive is true, app-item-detail will render:</p>
<!-- #docregion NgIf-1 -->
<app-item-detail *ngIf="isActive" [item]="item"></app-item-detail>
<!-- #enddocregion NgIf-1 -->
<button type="button" (click)="isActiveToggle()">Toggle app-item-detail</button>
</div>
<p>If currentCustomer isn't null, say hello to Laura:</p>
<!-- #docregion NgIf-2 -->
<div *ngIf="currentCustomer">Hello, {{ currentCustomer.name }}</div>
<!-- #enddocregion NgIf-2 -->
<p>nullCustomer is null by default. NgIf guards against null. Give it a value to show it:</p>
<!-- #docregion NgIf-2b -->
<div *ngIf="nullCustomer">
Hello, <span>{{ nullCustomer }}</span>
</div>
<!-- #enddocregion NgIf-2b -->
<button type="button" (click)="giveNullCustomerValue()">Give nullCustomer a value</button>
<h4>NgIf binding with template (no *)</h4>
<ng-template [ngIf]="currentItem">Add {{ currentItem.name }} with template</ng-template>
<hr />
<h4>Show/hide vs. NgIf</h4>
<!-- isSpecial is true -->
<div [class.hidden]="!isSpecial">Show with class</div>
<div [class.hidden]="isSpecial">Hide with class</div>
<p>ItemDetail is in the DOM but hidden</p>
<app-item-detail [class.hidden]="isSpecial"></app-item-detail>
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
<hr />
<h2 id="ngFor">NgFor Binding</h2>
<div class="box">
<!-- #docregion NgFor-1, NgFor-1-2 -->
<div *ngFor="let item of items">{{ item.name }}</div>
<!-- #enddocregion NgFor-1, NgFor-1-2 -->
</div>
<p>*ngFor with ItemDetailComponent element</p>
<div class="box">
<!-- #docregion NgFor-2, NgFor-1-2 -->
<app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail>
<!-- #enddocregion NgFor-2, NgFor-1-2 -->
</div>
<h4 id="ngFor-index">*ngFor with index</h4>
<p>with <em>semi-colon</em> separator</p>
<div class="box">
<!-- #docregion NgFor-3 -->
<div *ngFor="let item of items; let i = index">{{ i + 1 }} - {{ item.name }}</div>
<!-- #enddocregion NgFor-3 -->
</div>
<p>with <em>comma</em> separator</p>
<div class="box">
<div *ngFor="let item of items; let i = index">{{ i + 1 }} - {{ item.name }}</div>
</div>
<h4 id="ngFor-trackBy">*ngFor trackBy</h4>
<button type="button" (click)="resetList()">Reset items</button>
<button type="button" (click)="changeIds()">Change ids</button>
<button type="button" (click)="clearTrackByCounts()">Clear counts</button>
<p><em>without</em> trackBy</p>
<div class="box">
<div #noTrackBy *ngFor="let item of items">({{ item.id }}) {{ item.name }}</div>
<div id="noTrackByCnt" *ngIf="itemsNoTrackByCount">
Item DOM elements change #{{ itemsNoTrackByCount }} without trackBy
</div>
</div>
<p>with trackBy</p>
<div class="box">
<div #withTrackBy *ngFor="let item of items; trackBy: trackByItems">
({{ item.id }}) {{ item.name }}
</div>
<div id="withTrackByCnt" *ngIf="itemsWithTrackByCount">
Item DOM elements change #{{ itemsWithTrackByCount }} with trackBy
</div>
</div>
<br /><br /><br />
<p>with trackBy and <em>semi-colon</em> separator</p>
<div class="box">
<!-- #docregion trackBy -->
<div *ngFor="let item of items; trackBy: trackByItems">({{ item.id }}) {{ item.name }}</div>
<!-- #enddocregion trackBy -->
</div>
<p>with trackBy and <em>comma</em> separator</p>
<div class="box">
<div *ngFor="let item of items; trackBy: trackByItems">({{ item.id }}) {{ item.name }}</div>
</div>
<p>with trackBy and <em>space</em> separator</p>
<div class="box">
<div *ngFor="let item of items; trackBy: trackByItems">({{ item.id }}) {{ item.name }}</div>
</div>
<p>with <em>generic</em> trackById function</p>
<div class="box">
<div *ngFor="let item of items; trackBy: trackById">({{ item.id }}) {{ item.name }}</div>
</div>
<hr />
<h2>NgSwitch Binding</h2>
<p>Pick your favorite item</p>
<div>
<label for="item-{{ i }}" *ngFor="let i of items">
<div>
<input id="item-{{ i }}" type="radio" name="items" [(ngModel)]="currentItem" [value]="i" />{{
i.name
}}
</div>
</label>
</div>
<!-- #docregion NgSwitch -->
<div [ngSwitch]="currentItem.feature">
<app-stout-item *ngSwitchCase="'stout'" [item]="currentItem"></app-stout-item>
<app-device-item *ngSwitchCase="'slim'" [item]="currentItem"></app-device-item>
<app-lost-item *ngSwitchCase="'vintage'" [item]="currentItem"></app-lost-item>
<app-best-item *ngSwitchCase="'bright'" [item]="currentItem"></app-best-item>
<!-- #enddocregion NgSwitch -->
<!-- #docregion NgSwitch-div -->
<div *ngSwitchCase="'bright'">Are you as bright as {{ currentItem.name }}?</div>
<!-- #enddocregion NgSwitch-div -->
<!-- #docregion NgSwitch -->
<app-unknown-item *ngSwitchDefault [item]="currentItem"></app-unknown-item>
</div>
<!-- #enddocregion NgSwitch -->استفاده از NgClass با یک method
در مثال زیر، setCurrentClasses() property مربوط به currentClasses را با objectی set میکند که بر اساس state مربوط به true یا false سه property دیگر component، سه class را اضافه یا حذف میکند.
- برای استفاده از
NgClassبا یک method، آن method را به کلاس component اضافه کنید.
هر key در object یک نام CSS class است. اگر یک key برابر true باشد، ngClass آن class را اضافه میکند. اگر یک key برابر false باشد، ngClass آن class را حذف میکند.
import {Component, OnInit} from '@angular/core';
import {JsonPipe, NgClass, NgStyle} from '@angular/common';
// #docregion import-ng-if
import {NgIf} from '@angular/common';
// #enddocregion import-ng-if
// #docregion import-ng-for
import {NgFor} from '@angular/common';
// #enddocregion import-ng-for
// #docregion import-ng-switch
import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
// #enddocregion import-ng-switch
// #docregion import-forms-module
import {FormsModule} from '@angular/forms';
// #enddocregion import-forms-module
import {Item} from './item';
import {ItemDetailComponent} from './item-detail/item-detail.component';
import {ItemSwitchComponents} from './item-switch.component';
import {StoutItemComponent} from './item-switch.component';
// #docregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
@Component({
// #enddocregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
imports: [
NgClass,
NgStyle,
// #docregion import-ng-if
NgIf, // <-- import into the component
// #enddocregion import-ng-if
// #docregion import-ng-for
NgFor, // <-- import into the component
// #enddocregion import-ng-for
// #docregion import-ng-switch
NgSwitch, // <-- import into the component
NgSwitchCase,
NgSwitchDefault,
// #enddocregion import-ng-switch
// #docregion import-forms-module
FormsModule, // <--- import into the component
// #enddocregion import-forms-module
JsonPipe,
ItemDetailComponent,
ItemSwitchComponents,
StoutItemComponent,
// #docregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
],
})
export class AppComponent implements OnInit {
// #enddocregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
canSave = true;
isSpecial = true;
isUnchanged = true;
isActive = true;
nullCustomer: string | null = null;
currentCustomer = {
name: 'Laura',
};
item!: Item; // defined to demonstrate template context precedence
items: Item[] = [];
// #docregion item
currentItem!: Item;
// #enddocregion item
// trackBy change counting
itemsNoTrackByCount = 0;
itemsWithTrackByCount = 0;
itemsWithTrackByCountReset = 0;
itemIdIncrement = 1;
// #docregion setClasses
currentClasses: Record<string, boolean> = {};
// #enddocregion setClasses
// #docregion setStyles
currentStyles: Record<string, string> = {};
// #enddocregion setStyles
ngOnInit() {
this.resetItems();
this.setCurrentClasses();
this.setCurrentStyles();
this.itemsNoTrackByCount = 0;
}
setUppercaseName(name: string) {
this.currentItem.name = name.toUpperCase();
}
// #docregion setClasses
setCurrentClasses() {
// CSS classes: added/removed per current state of component properties
this.currentClasses = {
saveable: this.canSave,
modified: !this.isUnchanged,
special: this.isSpecial,
};
}
// #enddocregion setClasses
// #docregion setStyles
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',
};
}
// #enddocregion setStyles
isActiveToggle() {
this.isActive = !this.isActive;
}
giveNullCustomerValue() {
this.nullCustomer = 'Kelly';
}
resetItems() {
this.items = Item.items.map((item) => item.clone());
this.currentItem = this.items[0];
this.item = this.currentItem;
}
resetList() {
this.resetItems();
this.itemsWithTrackByCountReset = 0;
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
}
changeIds() {
this.items.forEach((i) => (i.id += 1 * this.itemIdIncrement));
this.itemsWithTrackByCountReset = -1;
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
this.itemsWithTrackByCount = ++this.itemsWithTrackByCount;
}
clearTrackByCounts() {
this.resetItems();
this.itemsNoTrackByCount = 0;
this.itemsWithTrackByCount = 0;
this.itemIdIncrement = 1;
}
// #docregion trackByItems
trackByItems(index: number, item: Item): number {
return item.id;
}
// #enddocregion trackByItems
trackById(index: number, item: any): number {
return item.id;
}
getValue(event: Event): string {
return (event.target as HTMLInputElement).value;
}
// #docregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
}
// #enddocregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module- در template، property binding مربوط به
ngClassرا بهcurrentClassesاضافه کنید تا classهای element تنظیم شوند:
<h1>Built-in Directives</h1>
<h2>Built-in attribute directives</h2>
<h3 id="ngModel">NgModel (two-way) Binding</h3>
<fieldset>
<h4>NgModel examples</h4>
<p>Current item name: {{ currentItem.name }}</p>
<p>
<label for="without">without NgModel:</label>
<input [value]="currentItem.name" (input)="currentItem.name = getValue($event)" id="without" />
</p>
<p>
<!-- #docregion NgModel-1 -->
<label for="example-ngModel">[(ngModel)]:</label>
<input [(ngModel)]="currentItem.name" id="example-ngModel" />
<!-- #enddocregion NgModel-1 -->
</p>
<p>
<label for="example-change">(ngModelChange)="...name=$event":</label>
<input
[ngModel]="currentItem.name"
(ngModelChange)="currentItem.name = $event"
id="example-change"
/>
</p>
<p>
<label for="example-uppercase"
>(ngModelChange)="setUppercaseName($event)"
<!-- #docregion uppercase -->
<input
[ngModel]="currentItem.name"
(ngModelChange)="setUppercaseName($event)"
id="example-uppercase"
/>
<!-- #enddocregion uppercase -->
</label>
</p>
</fieldset>
<hr />
<h2 id="ngClass">NgClass Binding</h2>
<p>currentClasses is {{ currentClasses | json }}</p>
<!-- #docregion NgClass-1 -->
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div>
<!-- #enddocregion NgClass-1 -->
<ul>
<li>
<label for="saveable">saveable</label>
<input type="checkbox" [(ngModel)]="canSave" id="saveable" />
</li>
<li>
<label for="modified">modified:</label>
<input
type="checkbox"
[value]="!isUnchanged"
(change)="isUnchanged = !isUnchanged"
id="modified"
/>
</li>
<li>
<label for="special"
>special: <input type="checkbox" [(ngModel)]="isSpecial" id="special"
/></label>
</li>
</ul>
<button type="button" (click)="setCurrentClasses()">Refresh currentClasses</button>
<div [ngClass]="currentClasses">
This div should be {{ canSave ? '' : 'not' }} saveable,
{{ isUnchanged ? 'unchanged' : 'modified' }} and {{ isSpecial ? '' : 'not' }} special after
clicking "Refresh".
</div>
<br /><br />
<!-- #docregion special-div -->
<!-- toggle the "special" class on/off with a property -->
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
<!-- #enddocregion special-div -->
<div class="helpful study course">Helpful study course</div>
<div [ngClass]="{'helpful': false, 'study': true, 'course': true}">Study course</div>
<!-- NgStyle binding -->
<hr />
<h3>NgStyle Binding</h3>
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'">This div is x-large or smaller.</div>
<h4>[ngStyle] binding to currentStyles - CSS property names</h4>
<p>currentStyles is {{ currentStyles | json }}</p>
<!-- #docregion NgStyle-2 -->
<div [ngStyle]="currentStyles">
This div is initially italic, normal weight, and extra large (24px).
</div>
<!-- #enddocregion NgStyle-2 -->
<br />
<label for="canSave">italic: <input id="canSave" type="checkbox" [(ngModel)]="canSave" /></label> |
<label for="isUnchanged"
>normal: <input id="isUnchanged" type="checkbox" [(ngModel)]="isUnchanged"
/></label>
|
<label for="isSpecial"
>xlarge: <input id="isSpecial" type="checkbox" [(ngModel)]="isSpecial"
/></label>
<button type="button" (click)="setCurrentStyles()">Refresh currentStyles</button>
<br /><br />
<div [ngStyle]="currentStyles">
This div should be {{ canSave ? 'italic' : 'plain' }},
{{ isUnchanged ? 'normal weight' : 'bold' }} and,
{{ isSpecial ? 'extra large' : 'normal size' }} after clicking "Refresh".
</div>
<hr />
<h2>Built-in structural directives</h2>
<h3 id="ngIf">NgIf Binding</h3>
<div>
<p>If isActive is true, app-item-detail will render:</p>
<!-- #docregion NgIf-1 -->
<app-item-detail *ngIf="isActive" [item]="item"></app-item-detail>
<!-- #enddocregion NgIf-1 -->
<button type="button" (click)="isActiveToggle()">Toggle app-item-detail</button>
</div>
<p>If currentCustomer isn't null, say hello to Laura:</p>
<!-- #docregion NgIf-2 -->
<div *ngIf="currentCustomer">Hello, {{ currentCustomer.name }}</div>
<!-- #enddocregion NgIf-2 -->
<p>nullCustomer is null by default. NgIf guards against null. Give it a value to show it:</p>
<!-- #docregion NgIf-2b -->
<div *ngIf="nullCustomer">
Hello, <span>{{ nullCustomer }}</span>
</div>
<!-- #enddocregion NgIf-2b -->
<button type="button" (click)="giveNullCustomerValue()">Give nullCustomer a value</button>
<h4>NgIf binding with template (no *)</h4>
<ng-template [ngIf]="currentItem">Add {{ currentItem.name }} with template</ng-template>
<hr />
<h4>Show/hide vs. NgIf</h4>
<!-- isSpecial is true -->
<div [class.hidden]="!isSpecial">Show with class</div>
<div [class.hidden]="isSpecial">Hide with class</div>
<p>ItemDetail is in the DOM but hidden</p>
<app-item-detail [class.hidden]="isSpecial"></app-item-detail>
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
<hr />
<h2 id="ngFor">NgFor Binding</h2>
<div class="box">
<!-- #docregion NgFor-1, NgFor-1-2 -->
<div *ngFor="let item of items">{{ item.name }}</div>
<!-- #enddocregion NgFor-1, NgFor-1-2 -->
</div>
<p>*ngFor with ItemDetailComponent element</p>
<div class="box">
<!-- #docregion NgFor-2, NgFor-1-2 -->
<app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail>
<!-- #enddocregion NgFor-2, NgFor-1-2 -->
</div>
<h4 id="ngFor-index">*ngFor with index</h4>
<p>with <em>semi-colon</em> separator</p>
<div class="box">
<!-- #docregion NgFor-3 -->
<div *ngFor="let item of items; let i = index">{{ i + 1 }} - {{ item.name }}</div>
<!-- #enddocregion NgFor-3 -->
</div>
<p>with <em>comma</em> separator</p>
<div class="box">
<div *ngFor="let item of items; let i = index">{{ i + 1 }} - {{ item.name }}</div>
</div>
<h4 id="ngFor-trackBy">*ngFor trackBy</h4>
<button type="button" (click)="resetList()">Reset items</button>
<button type="button" (click)="changeIds()">Change ids</button>
<button type="button" (click)="clearTrackByCounts()">Clear counts</button>
<p><em>without</em> trackBy</p>
<div class="box">
<div #noTrackBy *ngFor="let item of items">({{ item.id }}) {{ item.name }}</div>
<div id="noTrackByCnt" *ngIf="itemsNoTrackByCount">
Item DOM elements change #{{ itemsNoTrackByCount }} without trackBy
</div>
</div>
<p>with trackBy</p>
<div class="box">
<div #withTrackBy *ngFor="let item of items; trackBy: trackByItems">
({{ item.id }}) {{ item.name }}
</div>
<div id="withTrackByCnt" *ngIf="itemsWithTrackByCount">
Item DOM elements change #{{ itemsWithTrackByCount }} with trackBy
</div>
</div>
<br /><br /><br />
<p>with trackBy and <em>semi-colon</em> separator</p>
<div class="box">
<!-- #docregion trackBy -->
<div *ngFor="let item of items; trackBy: trackByItems">({{ item.id }}) {{ item.name }}</div>
<!-- #enddocregion trackBy -->
</div>
<p>with trackBy and <em>comma</em> separator</p>
<div class="box">
<div *ngFor="let item of items; trackBy: trackByItems">({{ item.id }}) {{ item.name }}</div>
</div>
<p>with trackBy and <em>space</em> separator</p>
<div class="box">
<div *ngFor="let item of items; trackBy: trackByItems">({{ item.id }}) {{ item.name }}</div>
</div>
<p>with <em>generic</em> trackById function</p>
<div class="box">
<div *ngFor="let item of items; trackBy: trackById">({{ item.id }}) {{ item.name }}</div>
</div>
<hr />
<h2>NgSwitch Binding</h2>
<p>Pick your favorite item</p>
<div>
<label for="item-{{ i }}" *ngFor="let i of items">
<div>
<input id="item-{{ i }}" type="radio" name="items" [(ngModel)]="currentItem" [value]="i" />{{
i.name
}}
</div>
</label>
</div>
<!-- #docregion NgSwitch -->
<div [ngSwitch]="currentItem.feature">
<app-stout-item *ngSwitchCase="'stout'" [item]="currentItem"></app-stout-item>
<app-device-item *ngSwitchCase="'slim'" [item]="currentItem"></app-device-item>
<app-lost-item *ngSwitchCase="'vintage'" [item]="currentItem"></app-lost-item>
<app-best-item *ngSwitchCase="'bright'" [item]="currentItem"></app-best-item>
<!-- #enddocregion NgSwitch -->
<!-- #docregion NgSwitch-div -->
<div *ngSwitchCase="'bright'">Are you as bright as {{ currentItem.name }}?</div>
<!-- #enddocregion NgSwitch-div -->
<!-- #docregion NgSwitch -->
<app-unknown-item *ngSwitchDefault [item]="currentItem"></app-unknown-item>
</div>
<!-- #enddocregion NgSwitch -->برای این use case، Angular classها را هنگام initialization و در صورت تغییرات ناشی از reassign شدن object مربوط به currentClasses اعمال میکند. مثال کامل در ابتدا با ngOnInit() و وقتی کاربر روی button مربوط به Refresh currentClasses کلیک میکند، setCurrentClasses() را فراخوانی میکند. این stepها برای پیادهسازی ngClass ضروری نیستند.
تنظیم inline styleها با NgStyle
Import کردن NgStyle در component
برای استفاده از NgStyle، آن را به list مربوط به imports در component اضافه کنید.
import {NgStyle} from '@angular/common';
@Component({
/* ... */
imports: [NgStyle],
})
export class AppComponent {}از NgStyle برای تنظیم همزمان چند inline style بر اساس state مربوط به component استفاده کنید.
- برای استفاده از
NgStyle، یک method به کلاس component اضافه کنید.
در مثال زیر، setCurrentStyles() property مربوط به currentStyles را با objectی set میکند که سه style را بر اساس state مربوط به سه property دیگر component تعریف میکند.
import {Component, OnInit} from '@angular/core';
import {JsonPipe, NgClass, NgStyle} from '@angular/common';
// #docregion import-ng-if
import {NgIf} from '@angular/common';
// #enddocregion import-ng-if
// #docregion import-ng-for
import {NgFor} from '@angular/common';
// #enddocregion import-ng-for
// #docregion import-ng-switch
import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';
// #enddocregion import-ng-switch
// #docregion import-forms-module
import {FormsModule} from '@angular/forms';
// #enddocregion import-forms-module
import {Item} from './item';
import {ItemDetailComponent} from './item-detail/item-detail.component';
import {ItemSwitchComponents} from './item-switch.component';
import {StoutItemComponent} from './item-switch.component';
// #docregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
@Component({
// #enddocregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
imports: [
NgClass,
NgStyle,
// #docregion import-ng-if
NgIf, // <-- import into the component
// #enddocregion import-ng-if
// #docregion import-ng-for
NgFor, // <-- import into the component
// #enddocregion import-ng-for
// #docregion import-ng-switch
NgSwitch, // <-- import into the component
NgSwitchCase,
NgSwitchDefault,
// #enddocregion import-ng-switch
// #docregion import-forms-module
FormsModule, // <--- import into the component
// #enddocregion import-forms-module
JsonPipe,
ItemDetailComponent,
ItemSwitchComponents,
StoutItemComponent,
// #docregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
],
})
export class AppComponent implements OnInit {
// #enddocregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
canSave = true;
isSpecial = true;
isUnchanged = true;
isActive = true;
nullCustomer: string | null = null;
currentCustomer = {
name: 'Laura',
};
item!: Item; // defined to demonstrate template context precedence
items: Item[] = [];
// #docregion item
currentItem!: Item;
// #enddocregion item
// trackBy change counting
itemsNoTrackByCount = 0;
itemsWithTrackByCount = 0;
itemsWithTrackByCountReset = 0;
itemIdIncrement = 1;
// #docregion setClasses
currentClasses: Record<string, boolean> = {};
// #enddocregion setClasses
// #docregion setStyles
currentStyles: Record<string, string> = {};
// #enddocregion setStyles
ngOnInit() {
this.resetItems();
this.setCurrentClasses();
this.setCurrentStyles();
this.itemsNoTrackByCount = 0;
}
setUppercaseName(name: string) {
this.currentItem.name = name.toUpperCase();
}
// #docregion setClasses
setCurrentClasses() {
// CSS classes: added/removed per current state of component properties
this.currentClasses = {
saveable: this.canSave,
modified: !this.isUnchanged,
special: this.isSpecial,
};
}
// #enddocregion setClasses
// #docregion setStyles
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',
};
}
// #enddocregion setStyles
isActiveToggle() {
this.isActive = !this.isActive;
}
giveNullCustomerValue() {
this.nullCustomer = 'Kelly';
}
resetItems() {
this.items = Item.items.map((item) => item.clone());
this.currentItem = this.items[0];
this.item = this.currentItem;
}
resetList() {
this.resetItems();
this.itemsWithTrackByCountReset = 0;
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
}
changeIds() {
this.items.forEach((i) => (i.id += 1 * this.itemIdIncrement));
this.itemsWithTrackByCountReset = -1;
this.itemsNoTrackByCount = ++this.itemsNoTrackByCount;
this.itemsWithTrackByCount = ++this.itemsWithTrackByCount;
}
clearTrackByCounts() {
this.resetItems();
this.itemsNoTrackByCount = 0;
this.itemsWithTrackByCount = 0;
this.itemIdIncrement = 1;
}
// #docregion trackByItems
trackByItems(index: number, item: Item): number {
return item.id;
}
// #enddocregion trackByItems
trackById(index: number, item: any): number {
return item.id;
}
getValue(event: Event): string {
return (event.target as HTMLInputElement).value;
}
// #docregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module
}
// #enddocregion import-ng-if, import-ng-for, import-ng-switch, import-forms-module- برای تنظیم styleهای element، یک property binding از نوع
ngStyleبهcurrentStylesاضافه کنید.
<h1>Built-in Directives</h1>
<h2>Built-in attribute directives</h2>
<h3 id="ngModel">NgModel (two-way) Binding</h3>
<fieldset>
<h4>NgModel examples</h4>
<p>Current item name: {{ currentItem.name }}</p>
<p>
<label for="without">without NgModel:</label>
<input [value]="currentItem.name" (input)="currentItem.name = getValue($event)" id="without" />
</p>
<p>
<!-- #docregion NgModel-1 -->
<label for="example-ngModel">[(ngModel)]:</label>
<input [(ngModel)]="currentItem.name" id="example-ngModel" />
<!-- #enddocregion NgModel-1 -->
</p>
<p>
<label for="example-change">(ngModelChange)="...name=$event":</label>
<input
[ngModel]="currentItem.name"
(ngModelChange)="currentItem.name = $event"
id="example-change"
/>
</p>
<p>
<label for="example-uppercase"
>(ngModelChange)="setUppercaseName($event)"
<!-- #docregion uppercase -->
<input
[ngModel]="currentItem.name"
(ngModelChange)="setUppercaseName($event)"
id="example-uppercase"
/>
<!-- #enddocregion uppercase -->
</label>
</p>
</fieldset>
<hr />
<h2 id="ngClass">NgClass Binding</h2>
<p>currentClasses is {{ currentClasses | json }}</p>
<!-- #docregion NgClass-1 -->
<div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div>
<!-- #enddocregion NgClass-1 -->
<ul>
<li>
<label for="saveable">saveable</label>
<input type="checkbox" [(ngModel)]="canSave" id="saveable" />
</li>
<li>
<label for="modified">modified:</label>
<input
type="checkbox"
[value]="!isUnchanged"
(change)="isUnchanged = !isUnchanged"
id="modified"
/>
</li>
<li>
<label for="special"
>special: <input type="checkbox" [(ngModel)]="isSpecial" id="special"
/></label>
</li>
</ul>
<button type="button" (click)="setCurrentClasses()">Refresh currentClasses</button>
<div [ngClass]="currentClasses">
This div should be {{ canSave ? '' : 'not' }} saveable,
{{ isUnchanged ? 'unchanged' : 'modified' }} and {{ isSpecial ? '' : 'not' }} special after
clicking "Refresh".
</div>
<br /><br />
<!-- #docregion special-div -->
<!-- toggle the "special" class on/off with a property -->
<div [ngClass]="isSpecial ? 'special' : ''">This div is special</div>
<!-- #enddocregion special-div -->
<div class="helpful study course">Helpful study course</div>
<div [ngClass]="{'helpful': false, 'study': true, 'course': true}">Study course</div>
<!-- NgStyle binding -->
<hr />
<h3>NgStyle Binding</h3>
<div [style.font-size]="isSpecial ? 'x-large' : 'smaller'">This div is x-large or smaller.</div>
<h4>[ngStyle] binding to currentStyles - CSS property names</h4>
<p>currentStyles is {{ currentStyles | json }}</p>
<!-- #docregion NgStyle-2 -->
<div [ngStyle]="currentStyles">
This div is initially italic, normal weight, and extra large (24px).
</div>
<!-- #enddocregion NgStyle-2 -->
<br />
<label for="canSave">italic: <input id="canSave" type="checkbox" [(ngModel)]="canSave" /></label> |
<label for="isUnchanged"
>normal: <input id="isUnchanged" type="checkbox" [(ngModel)]="isUnchanged"
/></label>
|
<label for="isSpecial"
>xlarge: <input id="isSpecial" type="checkbox" [(ngModel)]="isSpecial"
/></label>
<button type="button" (click)="setCurrentStyles()">Refresh currentStyles</button>
<br /><br />
<div [ngStyle]="currentStyles">
This div should be {{ canSave ? 'italic' : 'plain' }},
{{ isUnchanged ? 'normal weight' : 'bold' }} and,
{{ isSpecial ? 'extra large' : 'normal size' }} after clicking "Refresh".
</div>
<hr />
<h2>Built-in structural directives</h2>
<h3 id="ngIf">NgIf Binding</h3>
<div>
<p>If isActive is true, app-item-detail will render:</p>
<!-- #docregion NgIf-1 -->
<app-item-detail *ngIf="isActive" [item]="item"></app-item-detail>
<!-- #enddocregion NgIf-1 -->
<button type="button" (click)="isActiveToggle()">Toggle app-item-detail</button>
</div>
<p>If currentCustomer isn't null, say hello to Laura:</p>
<!-- #docregion NgIf-2 -->
<div *ngIf="currentCustomer">Hello, {{ currentCustomer.name }}</div>
<!-- #enddocregion NgIf-2 -->
<p>nullCustomer is null by default. NgIf guards against null. Give it a value to show it:</p>
<!-- #docregion NgIf-2b -->
<div *ngIf="nullCustomer">
Hello, <span>{{ nullCustomer }}</span>
</div>
<!-- #enddocregion NgIf-2b -->
<button type="button" (click)="giveNullCustomerValue()">Give nullCustomer a value</button>
<h4>NgIf binding with template (no *)</h4>
<ng-template [ngIf]="currentItem">Add {{ currentItem.name }} with template</ng-template>
<hr />
<h4>Show/hide vs. NgIf</h4>
<!-- isSpecial is true -->
<div [class.hidden]="!isSpecial">Show with class</div>
<div [class.hidden]="isSpecial">Hide with class</div>
<p>ItemDetail is in the DOM but hidden</p>
<app-item-detail [class.hidden]="isSpecial"></app-item-detail>
<div [style.display]="isSpecial ? 'block' : 'none'">Show with style</div>
<div [style.display]="isSpecial ? 'none' : 'block'">Hide with style</div>
<hr />
<h2 id="ngFor">NgFor Binding</h2>
<div class="box">
<!-- #docregion NgFor-1, NgFor-1-2 -->
<div *ngFor="let item of items">{{ item.name }}</div>
<!-- #enddocregion NgFor-1, NgFor-1-2 -->
</div>
<p>*ngFor with ItemDetailComponent element</p>
<div class="box">
<!-- #docregion NgFor-2, NgFor-1-2 -->
<app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail>
<!-- #enddocregion NgFor-2, NgFor-1-2 -->
</div>
<h4 id="ngFor-index">*ngFor with index</h4>
<p>with <em>semi-colon</em> separator</p>
<div class="box">
<!-- #docregion NgFor-3 -->
<div *ngFor="let item of items; let i = index">{{ i + 1 }} - {{ item.name }}</div>
<!-- #enddocregion NgFor-3 -->
</div>
<p>with <em>comma</em> separator</p>
<div class="box">
<div *ngFor="let item of items; let i = index">{{ i + 1 }} - {{ item.name }}</div>
</div>
<h4 id="ngFor-trackBy">*ngFor trackBy</h4>
<button type="button" (click)="resetList()">Reset items</button>
<button type="button" (click)="changeIds()">Change ids</button>
<button type="button" (click)="clearTrackByCounts()">Clear counts</button>
<p><em>without</em> trackBy</p>
<div class="box">
<div #noTrackBy *ngFor="let item of items">({{ item.id }}) {{ item.name }}</div>
<div id="noTrackByCnt" *ngIf="itemsNoTrackByCount">
Item DOM elements change #{{ itemsNoTrackByCount }} without trackBy
</div>
</div>
<p>with trackBy</p>
<div class="box">
<div #withTrackBy *ngFor="let item of items; trackBy: trackByItems">
({{ item.id }}) {{ item.name }}
</div>
<div id="withTrackByCnt" *ngIf="itemsWithTrackByCount">
Item DOM elements change #{{ itemsWithTrackByCount }} with trackBy
</div>
</div>
<br /><br /><br />
<p>with trackBy and <em>semi-colon</em> separator</p>
<div class="box">
<!-- #docregion trackBy -->
<div *ngFor="let item of items; trackBy: trackByItems">({{ item.id }}) {{ item.name }}</div>
<!-- #enddocregion trackBy -->
</div>
<p>with trackBy and <em>comma</em> separator</p>
<div class="box">
<div *ngFor="let item of items; trackBy: trackByItems">({{ item.id }}) {{ item.name }}</div>
</div>
<p>with trackBy and <em>space</em> separator</p>
<div class="box">
<div *ngFor="let item of items; trackBy: trackByItems">({{ item.id }}) {{ item.name }}</div>
</div>
<p>with <em>generic</em> trackById function</p>
<div class="box">
<div *ngFor="let item of items; trackBy: trackById">({{ item.id }}) {{ item.name }}</div>
</div>
<hr />
<h2>NgSwitch Binding</h2>
<p>Pick your favorite item</p>
<div>
<label for="item-{{ i }}" *ngFor="let i of items">
<div>
<input id="item-{{ i }}" type="radio" name="items" [(ngModel)]="currentItem" [value]="i" />{{
i.name
}}
</div>
</label>
</div>
<!-- #docregion NgSwitch -->
<div [ngSwitch]="currentItem.feature">
<app-stout-item *ngSwitchCase="'stout'" [item]="currentItem"></app-stout-item>
<app-device-item *ngSwitchCase="'slim'" [item]="currentItem"></app-device-item>
<app-lost-item *ngSwitchCase="'vintage'" [item]="currentItem"></app-lost-item>
<app-best-item *ngSwitchCase="'bright'" [item]="currentItem"></app-best-item>
<!-- #enddocregion NgSwitch -->
<!-- #docregion NgSwitch-div -->
<div *ngSwitchCase="'bright'">Are you as bright as {{ currentItem.name }}?</div>
<!-- #enddocregion NgSwitch-div -->
<!-- #docregion NgSwitch -->
<app-unknown-item *ngSwitchDefault [item]="currentItem"></app-unknown-item>
</div>
<!-- #enddocregion NgSwitch -->برای این use case، Angular styleها را هنگام initialization و در صورت تغییرات اعمال میکند. برای این کار، مثال کامل در ابتدا با ngOnInit() و وقتی propertyهای dependent از طریق click روی button تغییر میکنند، setCurrentStyles() را فراخوانی میکند. با این حال، این stepها برای پیادهسازی خود ngStyle ضروری نیستند.