我有以下模板:

<div>
  <span>{{aVariable}}</span>
</div>

并希望以:

<div "let a = aVariable">
  <span>{{a}}</span>
</div>

有办法吗?


当前回答

你可以使用Angular 2中的template元素或Angular 4+中的ng-template在html代码中声明变量。

模板有一个上下文对象,它的属性可以使用let绑定语法分配给变量。注意,您必须为模板指定一个出口,但它可以是对模板本身的引用。

<ng-template #selfie [ngTemplateOutlet]="selfie"
    let-a="aVariable" [ngTemplateOutletContext]="{ aVariable: 123 }">
  <div>
    <span>{{a}}</span>
  </div>
</ng-template>

<!-- Output
<div>
  <span>123</span>
</div>
-->

您可以通过使用context对象的$implicit属性而不是自定义属性来减少代码量。

<ng-template #t [ngTemplateOutlet]="t"
    let-a [ngTemplateOutletContext]="{ $implicit: 123 }">
  <div>
    <span>{{a}}</span>
  </div>
</ng-template>

上下文对象可以是文字对象或任何其他绑定表达式。其他有效例子:

<!-- Use arbitrary binding expressions -->
<ng-template let-sum [ngTemplateOutletContext]="{ $implicit: 1 + 1 }">

<!-- Use pipes -->
<ng-template let-formatPi [ngTemplateOutletContext]="{ $implicit: 3.141592 | number:'3.1-5' }">

<!-- Use the result of a public method of your component -->
<ng-template let-root [ngTemplateOutletContext]="{ $implicit: sqrt(2116) }">

<!--
    You can create an alias for a public property of your component:
    anotherVariable: number = 123; 
-->
<ng-template let-aliased [ngTemplateOutletContext]="{ $implicit: anotherVariable }">

<!--
    The entire context object can be bound from a public property:
    ctx: { first: number, second: string } = { first: 123, second: "etc" }
-->
<ng-template let-a="first" let-b="second" [ngTemplateOutletContext]="ctx">

其他回答

如果你想要得到函数的响应并将其设置为变量,你可以像下面这样在模板中使用它,使用ng-container来避免修改模板。

<ng-container *ngIf="methodName(parameters) as respObject">
  {{respObject.name}}
</ng-container>

组件中的方法可以是

methodName(parameters: any): any {
  return {name: 'Test name'};
}

我试图做一些类似的事情,看起来这个问题已经在angular的新版本中得到了解决。

    <div *ngIf="things.car; let car">
      Nice {{ car }}!
    </div>
    <!-- Nice Honda! -->

我是https://www.npmjs.com/package/ng-let的作者

将数据作为局部变量共享到html组件模板的结构指令。

源代码:

import { Directive, Input, TemplateRef, ViewContainerRef } from '@angular/core';

interface NgLetContext<T> {
    ngLet: T;
    $implicit: T;
}

@Directive({
    // tslint:disable-next-line: directive-selector
    selector: '[ngLet]'
})
export class NgLetDirective<T> {

    private context: NgLetContext<T | null> = { ngLet: null, $implicit: null };
    private hasView: boolean = false;

    // eslint-disable-next-line no-unused-vars
    constructor(private viewContainer: ViewContainerRef, private templateRef: TemplateRef<NgLetContext<T>>) { }

    @Input()
    set ngLet(value: T) {
        this.context.$implicit = this.context.ngLet = value;
        if (!this.hasView) {
            this.viewContainer.createEmbeddedView(this.templateRef, this.context);
            this.hasView = true;
        }
    }

    /** @internal */
    public static ngLetUseIfTypeGuard: void;

    /**
     * Assert the correct type of the expression bound to the `NgLet` input within the template.
     *
     * The presence of this static field is a signal to the Ivy template type check compiler that
     * when the `NgLet` structural directive renders its template, the type of the expression bound
     * to `NgLet` should be narrowed in some way. For `NgLet`, the binding expression itself is used to
     * narrow its type, which allows the strictNullChecks feature of TypeScript to work with `NgLet`.
     */
    static ngTemplateGuard_ngLet: 'binding';

    /**
     * Asserts the correct type of the context for the template that `NgLet` will render.
     *
     * The presence of this method is a signal to the Ivy template type-check compiler that the
     * `NgLet` structural directive renders its template with a specific context type.
     */
    static ngTemplateContextGuard<T>(dir: NgLetDirective<T>, ctx: any): ctx is NgLetContext<Exclude<T, false | 0 | '' | null | undefined>> {
        return true;
    }
}

用法:

import { Component } from '@angular/core';
import { defer, Observable, timer } from 'rxjs';

@Component({
  selector: 'app-root',
  template: `
  <ng-container *ngLet="timer$ | async as time"> <!-- single subscription -->
    <div>
      1: {{ time }}
    </div>
    <div>
      2: {{ time }}
    </div>
  </ng-container>
  `,
})
export class AppComponent {
  timer$: Observable<number> = defer(() => timer(3000, 1000));
}

@yurzui的原始答案将不能从Angular 9开始工作,因为一个奇怪的问题,将Angular 8应用程序迁移到9。 然而,你仍然可以从ngVar指令中受益

<ng-template [ngVar]="variable">
your code
</ng-template>

尽管它可能会导致IDE警告:“变量未定义”

像这样试试

<ng-container
     [ngTemplateOutlet]="foo"
     [ngTemplateOutletContext]="{ test: 'Test' }"
></ng-container>

<ng-template #foo let-test="test">
    <div>{{ test }}</div>
</ng-template>