Guías Detalladas
Directivas

Directivas integradas

Las directivas son clases que añaden comportamiento adicional a elementos en tus aplicaciones Angular.

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

  1. Para usar NgClass con un método, añade el método a la clase del componente. En el siguiente ejemplo, setCurrentClasses() configura la propiedad currentClasses con un objeto que añade o elimina tres clases basándose en el estado true o false de otras tres propiedades del componente.

    Cada clave del objeto es un nombre de clase CSS. Si una clave es true, ngClass añade la clase. Si una clave es false, ngClass elimina 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;  }}
  2. En la plantilla, añade el enlace de propiedad ngClass a currentClasses para 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.

  1. Para usar NgStyle, añade un método a la clase del componente.

    En el siguiente ejemplo, setCurrentStyles() configura la propiedad currentStyles con 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;  }}
  2. Para configurar los estilos del elemento, añade un enlace de propiedad ngStyle a currentStyles.

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>
párrafo ngcontainer con estilo apropiado
  1. Importa la directiva ngModel desde FormsModule.

  2. Añade FormsModule a la sección de imports del módulo Angular relevante.

  3. 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>
    las opciones ngcontainer funcionan correctamente

Próximos pasos