/
githubmirror
/
angular
Обзор
Документация
Войти
/
githubmirror
/
angular
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/common/src/directives/ng_if.ts
289 строк
10 KB
SkyZeroZx
docs(docs-infra): Add build-time validation for API and guide links using route manifest
08 июл 2026, 20:24
08 июл 2026, 20:24
c1829f6
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC All Rights Reserved. * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://angular.dev/license */ import { Directive, EmbeddedViewRef, Input, ɵRuntimeError as RuntimeError, TemplateRef, ViewContainerRef, ɵstringify as stringify, } from '@angular/core'; import {RuntimeErrorCode} from '../errors'; /** * A structural directive that conditionally includes a template based on the value of * an expression coerced to Boolean. * When the expression evaluates to true, Angular renders the template * provided in a `then` clause, and when false or null, * Angular renders the template provided in an optional `else` clause. The default * template for the `else` clause is blank. * * A [shorthand form](guide/directives/structural-directives#structural-directive-shorthand) of the directive, * `*ngIf="condition"`, is generally used, provided * as an attribute of the anchor element for the inserted template. * Angular expands this into a more explicit version, in which the anchor element * is contained in an `<ng-template>` element. * * Simple form with shorthand syntax: * * ```html * <div *ngIf="condition">Content to render when condition is true.</div> * ``` * * Simple form with expanded syntax: * * ```html * <ng-template [ngIf]="condition"><div>Content to render when condition is * true.</div></ng-template> * ``` * * Form with an "else" block: * * ```html * <div *ngIf="condition; else elseBlock">Content to render when condition is true.</div> * <ng-template #elseBlock>Content to render when condition is false.</ng-template> * ``` * * Shorthand form with "then" and "else" blocks: * * ```html * <div *ngIf="condition; then thenBlock else elseBlock"></div> * <ng-template #thenBlock>Content to render when condition is true.</ng-template> * <ng-template #elseBlock>Content to render when condition is false.</ng-template> * ``` * * Form with storing the value locally: * * ```html * <div *ngIf="condition as value; else elseBlock">{{value}}</div> * <ng-template #elseBlock>Content to render when value is null.</ng-template> * ``` * * @usageNotes * * The `*ngIf` directive is most commonly used to conditionally show an inline template, * as seen in the following example. * The default `else` template is blank. * * {@example common/ngIf/ts/module.ts region='NgIfSimple'} * * ### Showing an alternative template using `else` * * To display a template when `expression` evaluates to false, use an `else` template * binding as shown in the following example. * The `else` binding points to an `<ng-template>` element labeled `#elseBlock`. * The template can be defined anywhere in the component view, but is typically placed right after * `ngIf` for readability. * * {@example common/ngIf/ts/module.ts region='NgIfElse'} * * ### Using an external `then` template * * In the previous example, the then-clause template is specified inline, as the content of the * tag that contains the `ngIf` directive. You can also specify a template that is defined * externally, by referencing a labeled `<ng-template>` element. When you do this, you can * change which template to use at runtime, as shown in the following example. * * {@example common/ngIf/ts/module.ts region='NgIfThenElse'} * * ### Storing a conditional result in a variable * * You might want to show a set of properties from the same object. If you are waiting * for asynchronous data, the object can be undefined. * In this case, you can use `ngIf` and store the result of the condition in a local * variable as shown in the following example. * * {@example common/ngIf/ts/module.ts region='NgIfAs'} * * This code uses only one `AsyncPipe`, so only one subscription is created. * The conditional statement stores the result of `userStream|async` in the local variable `user`. * You can then bind the local `user` repeatedly. * * The conditional displays the data only if `userStream` returns a value, * so you don't need to use the * safe-navigation-operator (`?.`) * to guard against null values when accessing properties. * You can display an alternative template while waiting for the data. * * ### Shorthand syntax * * The shorthand syntax `*ngIf` expands into two separate template specifications * for the "then" and "else" clauses. For example, consider the following shorthand statement, * that is meant to show a loading page while waiting for data to be loaded. * * ```html * <div class="hero-list" *ngIf="heroes else loading"> * ... * </div> * * <ng-template #loading> * <div>Loading...</div> * </ng-template> * ``` * * You can see that the "else" clause references the `<ng-template>` * with the `#loading` label, and the template for the "then" clause * is provided as the content of the anchor element. * * However, when Angular expands the shorthand syntax, it creates * another `<ng-template>` tag, with `ngIf` and `ngIfElse` directives. * The anchor element containing the template for the "then" clause becomes * the content of this unlabeled `<ng-template>` tag. * * ```html * <ng-template [ngIf]="heroes" [ngIfElse]="loading"> * <div class="hero-list"> * ... * </div> * </ng-template> * * <ng-template #loading> * <div>Loading...</div> * </ng-template> * ``` * * The presence of the implicit template object has implications for the nesting of * structural directives. For more on this subject, see * [Structural Directives](guide/directives/structural-directives#one-structural-directive-per-element). * * @ngModule CommonModule * @publicApi * * @deprecated 20.0 * Use the `@if` block instead. Intent to remove in a future major release */ @Directive({ selector: '[ngIf]', }) export class NgIf<T = unknown> { private _context: NgIfContext<T> = new NgIfContext<T>(); private _thenTemplateRef: TemplateRef<NgIfContext<T>> | null = null; private _elseTemplateRef: TemplateRef<NgIfContext<T>> | null = null; private _thenViewRef: EmbeddedViewRef<NgIfContext<T>> | null = null; private _elseViewRef: EmbeddedViewRef<NgIfContext<T>> | null = null; constructor( private _viewContainer: ViewContainerRef, templateRef: TemplateRef<NgIfContext<T>>, ) { this._thenTemplateRef = templateRef; } /** * The Boolean expression to evaluate as the condition for showing a template. * @deprecated Use the `@if` block instead. Intent to remove in a future major release */ @Input() set ngIf(condition: T) { this._context.$implicit = this._context.ngIf = condition; this._updateView(); } /** * A template to show if the condition expression evaluates to true. * @deprecated Use the `@if` block instead. Intent to remove in a future major release */ @Input() set ngIfThen(templateRef: TemplateRef<NgIfContext<T>> | null) { assertTemplate(templateRef, (typeof ngDevMode === 'undefined' || ngDevMode) && 'ngIfThen'); this._thenTemplateRef = templateRef; this._thenViewRef = null; // clear previous view if any. this._updateView(); } /** * A template to show if the condition expression evaluates to false. * @deprecated Use the `@if` block instead. Intent to remove in a future major release */ @Input() set ngIfElse(templateRef: TemplateRef<NgIfContext<T>> | null) { assertTemplate(templateRef, (typeof ngDevMode === 'undefined' || ngDevMode) && 'ngIfElse'); this._elseTemplateRef = templateRef; this._elseViewRef = null; // clear previous view if any. this._updateView(); } private _updateView() { if (this._context.$implicit) { if (!this._thenViewRef) { this._viewContainer.clear(); this._elseViewRef = null; if (this._thenTemplateRef) { this._thenViewRef = this._viewContainer.createEmbeddedView( this._thenTemplateRef, this._context, ); } } } else { if (!this._elseViewRef) { this._viewContainer.clear(); this._thenViewRef = null; if (this._elseTemplateRef) { this._elseViewRef = this._viewContainer.createEmbeddedView( this._elseTemplateRef, this._context, ); } } } } /** @internal */ public static ngIfUseIfTypeGuard: void; /** * Assert the correct type of the expression bound to the `ngIf` input within the template. * * The presence of this static field is a signal to the Ivy template type check compiler that * when the `NgIf` structural directive renders its template, the type of the expression bound * to `ngIf` should be narrowed in some way. For `NgIf`, the binding expression itself is used to * narrow its type, which allows the strictNullChecks feature of TypeScript to work with `NgIf`. */ static ngTemplateGuard_ngIf: 'binding'; /** * Asserts the correct type of the context for the template that `NgIf` will render. * * The presence of this method is a signal to the Ivy template type-check compiler that the * `NgIf` structural directive renders its template with a specific context type. */ static ngTemplateContextGuard<T>( dir: NgIf<T>, ctx: any, ): ctx is NgIfContext<Exclude<T, false | 0 | '' | null | undefined>> { return true; } } /** * @publicApi * * @deprecated 20.0 * The ngIf directive is deprecated in favor of the @if block instead. */ export class NgIfContext<T = unknown> { public $implicit: T = null!; public ngIf: T = null!; } function assertTemplate( templateRef: TemplateRef<any> | null, property: string | false | null, ): void { if (templateRef && !templateRef.createEmbeddedView) { throw new RuntimeError( RuntimeErrorCode.NG_IF_NOT_A_TEMPLATE_REF, (typeof ngDevMode === 'undefined' || ngDevMode) && `${property} must be a TemplateRef, but received '${stringify(templateRef)}'.`, ); } }