Usa las directivas integradas de Angular para gestionar formularios, listas, estilos y lo que ven los usuarios.
Los diferentes tipos de directivas de Angular son los siguientes:
| Tipos de Directivas | Detalles |
|---|---|
| Componentes | Se usan con una plantilla. Este tipo de directiva es el tipo de directiva más común. |
| Directivas de atributo | Cambian la apariencia o comportamiento de un elemento, componente u otra directiva. |
| Structural directives | Cambia el diseño del DOM agregando y eliminando elementos del DOM.. |
Esta guía cubre las directivas de atributo integradas.
Directivas de atributo integradas
Las directivas de atributo escuchan y modifican el comportamiento de otros elementos HTML, atributos, propiedades y componentes.
Las directivas de atributo más comunes son las siguientes:
| Directivas comunes | Detalles |
|---|---|
NgClass |
Añade y elimina un conjunto de clases CSS. |
NgStyle |
Añade y elimina un conjunto de estilos HTML. |
NgModel |
Añade enlace de datos bidireccional a un elemento de formulario HTML. |
ÚTIL: Las directivas integradas usan solo APIs públicas. No tienen acceso especial a ninguna API privada que otras directivas no puedan acceder.
Añadiendo y eliminando clases con NgClass
Añade o elimina múltiples clases CSS simultáneamente con ngClass.
ÚTIL: Para añadir o eliminar una sola clase, usa enlace de clase en lugar de NgClass.
Importar NgClass en el componente
Para usar NgClass, añádelo a la lista de imports del componente.
src/app/app.component.ts (importación de NgClass)
import {Component, OnInit} from '@angular/core';import {JsonPipe} from '@angular/common';import {NgIf} from '@angular/common';import {NgFor} from '@angular/common';import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';import {NgStyle} from '@angular/common';import {NgClass} from '@angular/common';import {FormsModule} from '@angular/forms';import {Item} from './item';import {ItemDetailComponent} from './item-detail/item-detail.component';import {ItemSwitchComponents} from './item-switch.component';import {StoutItemComponent} from './item-switch.component';@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], imports: [ NgIf, // <-- import into the component NgFor, // <-- import into the component NgStyle, // <-- import into the component NgSwitch, // <-- import into the component NgSwitchCase, NgSwitchDefault, NgClass, // <-- import into the component FormsModule, // <--- import into the component JsonPipe, ItemDetailComponent, ItemSwitchComponents, StoutItemComponent, ],})export class AppComponent implements OnInit { 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[] = []; currentItem!: Item; // trackBy change counting itemsNoTrackByCount = 0; itemsWithTrackByCount = 0; itemsWithTrackByCountReset = 0; itemIdIncrement = 1; currentClasses: Record<string, boolean> = {}; currentStyles: Record<string, string> = {}; ngOnInit() { this.resetItems(); this.setCurrentClasses(); this.setCurrentStyles(); this.itemsNoTrackByCount = 0; } setUppercaseName(name: string) { this.currentItem.name = name.toUpperCase(); } setCurrentClasses() { // CSS classes: added/removed per current state of component properties this.currentClasses = { saveable: this.canSave, modified: !this.isUnchanged, special: this.isSpecial, }; } 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', }; } 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; } trackByItems(index: number, item: Item): number { return item.id; } trackById(index: number, item: any): number { return item.id; } getValue(event: Event): string { return (event.target as HTMLInputElement).value; }}
Usando NgClass con una expresión
En el elemento que quieres estilizar, añade [ngClass] y configúralo igual a una expresión.
En este caso, isSpecial es un booleano configurado como true en app.component.ts.
Como isSpecial es verdadero, ngClass aplica la clase special al <div>.
src/app/app.component.html
<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> <label for="example-ngModel">[(ngModel)]:</label> <input [(ngModel)]="currentItem.name" id="example-ngModel"> </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)" <input [ngModel]="currentItem.name" (ngModelChange)="setUppercaseName($event)" id="example-uppercase"> </label> </p></fieldset><hr><h2 id="ngClass">NgClass Binding</h2><p>currentClasses is {{ currentClasses | json }}</p><div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div><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><!-- toggle the "special" class on/off with a property --><div [ngClass]="isSpecial ? 'special' : ''">This div is 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><div [ngStyle]="currentStyles"> This div is initially italic, normal weight, and extra large (24px).</div><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> <app-item-detail *ngIf="isActive" [item]="item"></app-item-detail> <button type="button" (click)="isActiveToggle()">Toggle app-item-detail</button></div><p>If currentCustomer isn't null, say hello to Laura:</p><div *ngIf="currentCustomer">Hello, {{ currentCustomer.name }}</div><p>nullCustomer is null by default. NgIf guards against null. Give it a value to show it:</p><div *ngIf="nullCustomer">Hello, <span>{{ nullCustomer }}</span></div><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"> <div *ngFor="let item of items">{{ item.name }}</div></div><p>*ngFor with ItemDetailComponent element</p><div class="box"> <app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail></div><h4 id="ngFor-index">*ngFor with index</h4><p>with <em>semi-colon</em> separator</p><div class="box"> <div *ngFor="let item of items; let i=index">{{ i + 1 }} - {{ item.name }}</div></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"> <div *ngFor="let item of items; trackBy: trackByItems"> ({{ item.id }}) {{ item.name }} </div></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><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> <div *ngSwitchCase="'bright'">Are you as bright as {{ currentItem.name }}?</div> <app-unknown-item *ngSwitchDefault [item]="currentItem"></app-unknown-item></div>
Usando NgClass con un método
Para usar
NgClasscon un método, añade el método a la clase del componente. En el siguiente ejemplo,setCurrentClasses()configura la propiedadcurrentClassescon un objeto que añade o elimina tres clases basándose en el estadotrueofalsede otras tres propiedades del componente.Cada clave del objeto es un nombre de clase CSS. Si una clave es
true,ngClassañade la clase. Si una clave esfalse,ngClasselimina la clase.src/app/app.component.ts
import {Component, OnInit} from '@angular/core';import {JsonPipe} from '@angular/common';import {NgIf} from '@angular/common';import {NgFor} from '@angular/common';import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';import {NgStyle} from '@angular/common';import {NgClass} from '@angular/common';import {FormsModule} from '@angular/forms';import {Item} from './item';import {ItemDetailComponent} from './item-detail/item-detail.component';import {ItemSwitchComponents} from './item-switch.component';import {StoutItemComponent} from './item-switch.component';@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], imports: [ NgIf, // <-- import into the component NgFor, // <-- import into the component NgStyle, // <-- import into the component NgSwitch, // <-- import into the component NgSwitchCase, NgSwitchDefault, NgClass, // <-- import into the component FormsModule, // <--- import into the component JsonPipe, ItemDetailComponent, ItemSwitchComponents, StoutItemComponent, ],})export class AppComponent implements OnInit { 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[] = []; currentItem!: Item; // trackBy change counting itemsNoTrackByCount = 0; itemsWithTrackByCount = 0; itemsWithTrackByCountReset = 0; itemIdIncrement = 1; currentClasses: Record<string, boolean> = {}; currentStyles: Record<string, string> = {}; ngOnInit() { this.resetItems(); this.setCurrentClasses(); this.setCurrentStyles(); this.itemsNoTrackByCount = 0; } setUppercaseName(name: string) { this.currentItem.name = name.toUpperCase(); } setCurrentClasses() { // CSS classes: added/removed per current state of component properties this.currentClasses = { saveable: this.canSave, modified: !this.isUnchanged, special: this.isSpecial, }; } 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', }; } 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; } trackByItems(index: number, item: Item): number { return item.id; } trackById(index: number, item: any): number { return item.id; } getValue(event: Event): string { return (event.target as HTMLInputElement).value; }}En la plantilla, añade el enlace de propiedad
ngClassacurrentClassespara configurar las clases del elemento:
src/app/app.component.html
<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> <label for="example-ngModel">[(ngModel)]:</label> <input [(ngModel)]="currentItem.name" id="example-ngModel"> </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)" <input [ngModel]="currentItem.name" (ngModelChange)="setUppercaseName($event)" id="example-uppercase"> </label> </p></fieldset><hr><h2 id="ngClass">NgClass Binding</h2><p>currentClasses is {{ currentClasses | json }}</p><div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div><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><!-- toggle the "special" class on/off with a property --><div [ngClass]="isSpecial ? 'special' : ''">This div is 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><div [ngStyle]="currentStyles"> This div is initially italic, normal weight, and extra large (24px).</div><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> <app-item-detail *ngIf="isActive" [item]="item"></app-item-detail> <button type="button" (click)="isActiveToggle()">Toggle app-item-detail</button></div><p>If currentCustomer isn't null, say hello to Laura:</p><div *ngIf="currentCustomer">Hello, {{ currentCustomer.name }}</div><p>nullCustomer is null by default. NgIf guards against null. Give it a value to show it:</p><div *ngIf="nullCustomer">Hello, <span>{{ nullCustomer }}</span></div><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"> <div *ngFor="let item of items">{{ item.name }}</div></div><p>*ngFor with ItemDetailComponent element</p><div class="box"> <app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail></div><h4 id="ngFor-index">*ngFor with index</h4><p>with <em>semi-colon</em> separator</p><div class="box"> <div *ngFor="let item of items; let i=index">{{ i + 1 }} - {{ item.name }}</div></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"> <div *ngFor="let item of items; trackBy: trackByItems"> ({{ item.id }}) {{ item.name }} </div></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><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> <div *ngSwitchCase="'bright'">Are you as bright as {{ currentItem.name }}?</div> <app-unknown-item *ngSwitchDefault [item]="currentItem"></app-unknown-item></div>
Para este caso de uso, Angular aplica las clases en la inicialización y en caso de cambios causados por reasignar el objeto currentClasses.
El ejemplo completo llama a setCurrentClasses() inicialmente con ngOnInit() cuando el usuario hace clic en el botón Refresh currentClasses.
Estos pasos no son necesarios para implementar ngClass.
Configurando estilos en línea con NgStyle
ÚTIL: Para añadir o eliminar un solo estilo, usa enlaces de estilo en lugar de NgStyle.
Importar NgStyle en el componente
Para usar NgStyle, añádelo a la lista de imports del componente.
src/app/app.component.ts (importación de NgStyle)
import {Component, OnInit} from '@angular/core';import {JsonPipe} from '@angular/common';import {NgIf} from '@angular/common';import {NgFor} from '@angular/common';import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';import {NgStyle} from '@angular/common';import {NgClass} from '@angular/common';import {FormsModule} from '@angular/forms';import {Item} from './item';import {ItemDetailComponent} from './item-detail/item-detail.component';import {ItemSwitchComponents} from './item-switch.component';import {StoutItemComponent} from './item-switch.component';@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], imports: [ NgIf, // <-- import into the component NgFor, // <-- import into the component NgStyle, // <-- import into the component NgSwitch, // <-- import into the component NgSwitchCase, NgSwitchDefault, NgClass, // <-- import into the component FormsModule, // <--- import into the component JsonPipe, ItemDetailComponent, ItemSwitchComponents, StoutItemComponent, ],})export class AppComponent implements OnInit { 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[] = []; currentItem!: Item; // trackBy change counting itemsNoTrackByCount = 0; itemsWithTrackByCount = 0; itemsWithTrackByCountReset = 0; itemIdIncrement = 1; currentClasses: Record<string, boolean> = {}; currentStyles: Record<string, string> = {}; ngOnInit() { this.resetItems(); this.setCurrentClasses(); this.setCurrentStyles(); this.itemsNoTrackByCount = 0; } setUppercaseName(name: string) { this.currentItem.name = name.toUpperCase(); } setCurrentClasses() { // CSS classes: added/removed per current state of component properties this.currentClasses = { saveable: this.canSave, modified: !this.isUnchanged, special: this.isSpecial, }; } 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', }; } 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; } trackByItems(index: number, item: Item): number { return item.id; } trackById(index: number, item: any): number { return item.id; } getValue(event: Event): string { return (event.target as HTMLInputElement).value; }}
Usa NgStyle para configurar múltiples estilos en línea simultáneamente, basándose en el estado del componente.
Para usar
NgStyle, añade un método a la clase del componente.En el siguiente ejemplo,
setCurrentStyles()configura la propiedadcurrentStylescon un objeto que define tres estilos, basándose en el estado de otras tres propiedades del componente.src/app/app.component.ts
import {Component, OnInit} from '@angular/core';import {JsonPipe} from '@angular/common';import {NgIf} from '@angular/common';import {NgFor} from '@angular/common';import {NgSwitch, NgSwitchCase, NgSwitchDefault} from '@angular/common';import {NgStyle} from '@angular/common';import {NgClass} from '@angular/common';import {FormsModule} from '@angular/forms';import {Item} from './item';import {ItemDetailComponent} from './item-detail/item-detail.component';import {ItemSwitchComponents} from './item-switch.component';import {StoutItemComponent} from './item-switch.component';@Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], imports: [ NgIf, // <-- import into the component NgFor, // <-- import into the component NgStyle, // <-- import into the component NgSwitch, // <-- import into the component NgSwitchCase, NgSwitchDefault, NgClass, // <-- import into the component FormsModule, // <--- import into the component JsonPipe, ItemDetailComponent, ItemSwitchComponents, StoutItemComponent, ],})export class AppComponent implements OnInit { 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[] = []; currentItem!: Item; // trackBy change counting itemsNoTrackByCount = 0; itemsWithTrackByCount = 0; itemsWithTrackByCountReset = 0; itemIdIncrement = 1; currentClasses: Record<string, boolean> = {}; currentStyles: Record<string, string> = {}; ngOnInit() { this.resetItems(); this.setCurrentClasses(); this.setCurrentStyles(); this.itemsNoTrackByCount = 0; } setUppercaseName(name: string) { this.currentItem.name = name.toUpperCase(); } setCurrentClasses() { // CSS classes: added/removed per current state of component properties this.currentClasses = { saveable: this.canSave, modified: !this.isUnchanged, special: this.isSpecial, }; } 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', }; } 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; } trackByItems(index: number, item: Item): number { return item.id; } trackById(index: number, item: any): number { return item.id; } getValue(event: Event): string { return (event.target as HTMLInputElement).value; }}Para configurar los estilos del elemento, añade un enlace de propiedad
ngStyleacurrentStyles.
src/app/app.component.html
<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> <label for="example-ngModel">[(ngModel)]:</label> <input [(ngModel)]="currentItem.name" id="example-ngModel"> </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)" <input [ngModel]="currentItem.name" (ngModelChange)="setUppercaseName($event)" id="example-uppercase"> </label> </p></fieldset><hr><h2 id="ngClass">NgClass Binding</h2><p>currentClasses is {{ currentClasses | json }}</p><div [ngClass]="currentClasses">This div is initially saveable, unchanged, and special.</div><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><!-- toggle the "special" class on/off with a property --><div [ngClass]="isSpecial ? 'special' : ''">This div is 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><div [ngStyle]="currentStyles"> This div is initially italic, normal weight, and extra large (24px).</div><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> <app-item-detail *ngIf="isActive" [item]="item"></app-item-detail> <button type="button" (click)="isActiveToggle()">Toggle app-item-detail</button></div><p>If currentCustomer isn't null, say hello to Laura:</p><div *ngIf="currentCustomer">Hello, {{ currentCustomer.name }}</div><p>nullCustomer is null by default. NgIf guards against null. Give it a value to show it:</p><div *ngIf="nullCustomer">Hello, <span>{{ nullCustomer }}</span></div><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"> <div *ngFor="let item of items">{{ item.name }}</div></div><p>*ngFor with ItemDetailComponent element</p><div class="box"> <app-item-detail *ngFor="let item of items" [item]="item"></app-item-detail></div><h4 id="ngFor-index">*ngFor with index</h4><p>with <em>semi-colon</em> separator</p><div class="box"> <div *ngFor="let item of items; let i=index">{{ i + 1 }} - {{ item.name }}</div></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"> <div *ngFor="let item of items; trackBy: trackByItems"> ({{ item.id }}) {{ item.name }} </div></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><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> <div *ngSwitchCase="'bright'">Are you as bright as {{ currentItem.name }}?</div> <app-unknown-item *ngSwitchDefault [item]="currentItem"></app-unknown-item></div>
Para este caso de uso, Angular aplica los estilos en la inicialización y en caso de cambios.
Para hacer esto, el ejemplo completo llama a setCurrentStyles() inicialmente con ngOnInit() y cuando las propiedades dependientes cambian a través de un clic de botón.
Sin embargo, estos pasos no son necesarios para implementar ngStyle por sí solo.
Alojando una directiva sin un elemento DOM
El <ng-container> de Angular es un elemento de agrupación que no interfiere con estilos o diseño porque Angular no lo pone en el DOM.
Usa <ng-container> cuando no hay un solo elemento para alojar la directiva.
Aquí hay un párrafo condicional usando <ng-container>.
src/app/app.component.html (ngif-ngcontainer)
<h1>Structural Directives</h1><p>Conditional display of hero</p><blockquote><div *ngIf="hero" class="name">{{hero.name}}</div></blockquote><p>List of heroes</p><ul> <li *ngFor="let hero of heroes">{{hero.name}}</li></ul><hr><h2 id="ngIf">NgIf</h2><p *ngIf="true"> Expression is true and ngIf is true. This paragraph is in the DOM.</p><p *ngIf="false"> Expression is false and ngIf is false. This paragraph is not in the DOM.</p><p [style.display]="'block'"> Expression sets display to "block". This paragraph is visible.</p><p [style.display]="'none'"> Expression sets display to "none". This paragraph is hidden but still in the DOM.</p><h4>NgIf with template</h4><p><ng-template> element</p><ng-template [ngIf]="hero"> <div class="name">{{hero.name}}</div></ng-template><hr><h2 id="ng-container"><ng-container></h2><h4>*ngIf with a <ng-container></h4><button type="button" (click)="hero = hero ? null : heroes[0]">Toggle hero</button><p> I turned the corner <ng-container *ngIf="hero"> and saw {{hero.name}}. I waved </ng-container> and continued on my way.</p><p> I turned the corner <span *ngIf="hero"> and saw {{hero.name}}. I waved </span> and continued on my way.</p><p><em><select> with <span></em></p><div> Pick your favorite hero (<label for="show-sad"><input id="show-sad" type="checkbox" checked (change)="showSad = !showSad">show sad</label>)</div><select [(ngModel)]="hero"> <span *ngFor="let h of heroes"> <span *ngIf="showSad || h.emotion !== 'sad'"> <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option> </span> </span></select><p><em><select> with <ng-container></em></p><div> Pick your favorite hero (<label for="showSad"><input id="showSad" type="checkbox" checked (change)="showSad = !showSad">show sad</label>)</div><select [(ngModel)]="hero"> <ng-container *ngFor="let h of heroes"> <ng-container *ngIf="showSad || h.emotion !== 'sad'"> <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option> </ng-container> </ng-container></select><br><br><hr><h2 id="ngFor">NgFor</h2><div class="box"><p class="code"><div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"></p><div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"> ({{i}}) {{hero.name}}</div><p class="code"><ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"/></p><ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"> <div [class.odd]="odd"> ({{i}}) {{hero.name}} </div></ng-template></div><hr><h2 id="ngSwitch">NgSwitch</h2><div>Pick your favorite hero</div><p> <label for="hero-{{h}}" *ngFor="let h of heroes"> <input id="hero-{{h}}" type="radio" name="heroes" [(ngModel)]="hero" [value]="h">{{h.name}} </label> <label for="none-of-the-above"><input id="none-of-the-above" type="radio" name="heroes" (click)="hero = null">None of the above</label></p><h4>NgSwitch</h4><div [ngSwitch]="hero?.emotion"> <app-happy-hero *ngSwitchCase="'happy'" [hero]="hero!"></app-happy-hero> <app-sad-hero *ngSwitchCase="'sad'" [hero]="hero!"></app-sad-hero> <app-confused-hero *ngSwitchCase="'confused'" [hero]="hero!"></app-confused-hero> <app-unknown-hero *ngSwitchDefault [hero]="hero!"></app-unknown-hero></div><h4>NgSwitch with <ng-template></h4><div [ngSwitch]="hero?.emotion"> <ng-template ngSwitchCase="happy"> <app-happy-hero [hero]="hero!"></app-happy-hero> </ng-template> <ng-template ngSwitchCase="sad"> <app-sad-hero [hero]="hero!"></app-sad-hero> </ng-template> <ng-template ngSwitchCase="confused"> <app-confused-hero [hero]="hero!"></app-confused-hero> </ng-template > <ng-template ngSwitchDefault> <app-unknown-hero [hero]="hero!"></app-unknown-hero> </ng-template></div><hr><hr><h2 id="appIfLoaded">IfLoadedDirective</h2><app-hero></app-hero><hr><h2 id="appTrigonometry">TrigonometryDirective</h2><ul *appTrigonometry="30; sin as s; cos as c; tan as t"> <li>sin(30°): {{ s }}</li> <li>cos(30°): {{ c }}</li> <li>tan(30°): {{ t }}</li></ul>
Importa la directiva
ngModeldesdeFormsModule.Añade
FormsModulea la sección de imports del módulo Angular relevante.Para excluir condicionalmente una
<option>, envuelve la<option>en un<ng-container>.src/app/app.component.html (select-ngcontainer)
<h1>Structural Directives</h1><p>Conditional display of hero</p><blockquote><div *ngIf="hero" class="name">{{hero.name}}</div></blockquote><p>List of heroes</p><ul> <li *ngFor="let hero of heroes">{{hero.name}}</li></ul><hr><h2 id="ngIf">NgIf</h2><p *ngIf="true"> Expression is true and ngIf is true. This paragraph is in the DOM.</p><p *ngIf="false"> Expression is false and ngIf is false. This paragraph is not in the DOM.</p><p [style.display]="'block'"> Expression sets display to "block". This paragraph is visible.</p><p [style.display]="'none'"> Expression sets display to "none". This paragraph is hidden but still in the DOM.</p><h4>NgIf with template</h4><p><ng-template> element</p><ng-template [ngIf]="hero"> <div class="name">{{hero.name}}</div></ng-template><hr><h2 id="ng-container"><ng-container></h2><h4>*ngIf with a <ng-container></h4><button type="button" (click)="hero = hero ? null : heroes[0]">Toggle hero</button><p> I turned the corner <ng-container *ngIf="hero"> and saw {{hero.name}}. I waved </ng-container> and continued on my way.</p><p> I turned the corner <span *ngIf="hero"> and saw {{hero.name}}. I waved </span> and continued on my way.</p><p><em><select> with <span></em></p><div> Pick your favorite hero (<label for="show-sad"><input id="show-sad" type="checkbox" checked (change)="showSad = !showSad">show sad</label>)</div><select [(ngModel)]="hero"> <span *ngFor="let h of heroes"> <span *ngIf="showSad || h.emotion !== 'sad'"> <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option> </span> </span></select><p><em><select> with <ng-container></em></p><div> Pick your favorite hero (<label for="showSad"><input id="showSad" type="checkbox" checked (change)="showSad = !showSad">show sad</label>)</div><select [(ngModel)]="hero"> <ng-container *ngFor="let h of heroes"> <ng-container *ngIf="showSad || h.emotion !== 'sad'"> <option [ngValue]="h">{{h.name}} ({{h.emotion}})</option> </ng-container> </ng-container></select><br><br><hr><h2 id="ngFor">NgFor</h2><div class="box"><p class="code"><div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"></p><div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy: trackById" [class.odd]="odd"> ({{i}}) {{hero.name}}</div><p class="code"><ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"/></p><ng-template ngFor let-hero [ngForOf]="heroes" let-i="index" let-odd="odd" [ngForTrackBy]="trackById"> <div [class.odd]="odd"> ({{i}}) {{hero.name}} </div></ng-template></div><hr><h2 id="ngSwitch">NgSwitch</h2><div>Pick your favorite hero</div><p> <label for="hero-{{h}}" *ngFor="let h of heroes"> <input id="hero-{{h}}" type="radio" name="heroes" [(ngModel)]="hero" [value]="h">{{h.name}} </label> <label for="none-of-the-above"><input id="none-of-the-above" type="radio" name="heroes" (click)="hero = null">None of the above</label></p><h4>NgSwitch</h4><div [ngSwitch]="hero?.emotion"> <app-happy-hero *ngSwitchCase="'happy'" [hero]="hero!"></app-happy-hero> <app-sad-hero *ngSwitchCase="'sad'" [hero]="hero!"></app-sad-hero> <app-confused-hero *ngSwitchCase="'confused'" [hero]="hero!"></app-confused-hero> <app-unknown-hero *ngSwitchDefault [hero]="hero!"></app-unknown-hero></div><h4>NgSwitch with <ng-template></h4><div [ngSwitch]="hero?.emotion"> <ng-template ngSwitchCase="happy"> <app-happy-hero [hero]="hero!"></app-happy-hero> </ng-template> <ng-template ngSwitchCase="sad"> <app-sad-hero [hero]="hero!"></app-sad-hero> </ng-template> <ng-template ngSwitchCase="confused"> <app-confused-hero [hero]="hero!"></app-confused-hero> </ng-template > <ng-template ngSwitchDefault> <app-unknown-hero [hero]="hero!"></app-unknown-hero> </ng-template></div><hr><hr><h2 id="appIfLoaded">IfLoadedDirective</h2><app-hero></app-hero><hr><h2 id="appTrigonometry">TrigonometryDirective</h2><ul *appTrigonometry="30; sin as s; cos as c; tan as t"> <li>sin(30°): {{ s }}</li> <li>cos(30°): {{ c }}</li> <li>tan(30°): {{ t }}</li></ul>