我有以下模板:

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

并希望以:

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

有办法吗?


当前回答

下面是我编写的一个指令,它扩展了exportAs装饰器参数的使用,并允许您使用字典作为局部变量。

import { Directive, Input } from "@angular/core";
@Directive({
    selector:"[localVariables]",
    exportAs:"localVariables"
})
export class LocalVariables {
    @Input("localVariables") set localVariables( struct: any ) {
        if ( typeof struct === "object" ) {
            for( var variableName in struct ) {
                this[variableName] = struct[variableName];
            }
        }
    }
    constructor( ) {
    }
}

你可以在模板中使用它:

<div #local="localVariables" [localVariables]="{a: 1, b: 2, c: 3+2}">
   <span>a = {{local.a}}</span>
   <span>b = {{local.b}}</span>
   <span>c = {{local.c}}</span>
</div>

当然,#local可以是任何有效的局部变量名。

其他回答

更新3

问题https://github.com/angular/angular/issues/2451在Angular 4.0.0中已修复

另请参阅

https://github.com/angular/angular/pull/13297 https://github.com/angular/angular/commit/b4db73d https://github.com/angular/angular/issues/13061

更新2

这是不支持的。

有模板变量,但不支持分配任意值。它们只能用于引用它们应用的元素,导出指令或组件的名称,以及ngFor等结构指令的作用域变量,

参见https://github.com/angular/angular/issues/2451

更新1

@Directive({
  selector: '[var]',
  exportAs: 'var'
})
class VarDirective {
  @Input() var:any;
}

然后像这样初始化

<div #aVariable="var" var="abc"></div>

or

<div #aVariable="var" [var]="'abc'"></div>

然后用这个变量

<div>{{aVariable.var}}</div>

(未测试)

# variable创建对VarDirective的引用(exportAs: 'var') var="abc"实例化VarDirective,并将字符串值"abc"传递给它的值输入。 aVariable。Var读取分配给Var指令Var输入的值。

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

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

组件中的方法可以是

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

我使用的是angular 6x,我最终使用了下面的代码片段。 我有一个需要从任务对象中查找user的场景。它包含用户数组,但我必须选择分配的用户。

<ng-container *ngTemplateOutlet="memberTemplate; context:{o: getAssignee(task) }">
</ng-container>
<ng-template #memberTemplate let-user="o">
  <ng-container *ngIf="user">
    <div class="d-flex flex-row-reverse">
      <span class="image-block">
        <ngx-avatar placement="left" ngbTooltip="{{user.firstName}} {{user.lastName}}" class="task-assigned" value="28%" [src]="user.googleId" size="32"></ngx-avatar>
      </span>
    </div>
  </ng-container>
</ng-template>

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

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

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

对于那些决定使用结构指令代替*ngIf的人,请记住,默认情况下指令上下文不进行类型检查。要创建一个类型安全的指令,应该添加ngTemplateContextGuard属性,请参见输入指令的上下文。例如:

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

@Directive({
    // don't use 'ng' prefix since it's reserved for Angular
    selector: '[appVar]',
})
export class VarDirective<T = unknown> {
    // https://angular.io/guide/structural-directives#typing-the-directives-context
    static ngTemplateContextGuard<T>(dir: VarDirective<T>, ctx: any): ctx is Context<T> {
        return true;
    }

    private context?: Context<T>;

    constructor(
        private vcRef: ViewContainerRef,
        private templateRef: TemplateRef<Context<T>>
    ) {}

    @Input()
    set appVar(value: T) {
        if (this.context) {
            this.context.appVar = value;
        } else {
            this.context = { appVar: value };
            this.vcRef.createEmbeddedView(this.templateRef, this.context);
        }
    }
}

interface Context<T> {
    appVar: T;
}

该指令可以像*ngIf一样使用,除了它可以存储假值:

<ng-container *appVar="false as value">{{value}}</ng-container>

<!-- error: User doesn't have `nam` property-->
<ng-container *appVar="user as user">{{user.nam}}</ng-container>

<ng-container *appVar="user$ | async as user">{{user.name}}</ng-container>

与*ngIf相比,唯一的缺点是Angular语言服务无法识别变量类型,因此模板中没有代码补全功能。我希望它能很快修好。