如何在Angular中声明模板中的变量

Sci*_*ion 147 html angular

我有以下模板:

<div>
  <span>{{aVariable}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

并希望最终得到:

<div "let a = aVariable">
  <span>{{a}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

有办法吗?

yur*_*zui 116

更新

正如@Keith在评论中提到的那样

这在大多数情况下都有效,但它不是一般的解决方案,因为它依赖于变量的真实性

所以起源答案就像@Keith所说.这是另一种方法.我们可以像创建指令一样*ngIf调用它*ngVar

NG-var.directive.ts

@Directive({
    selector: '[ngVar]',
})
export class VarDirective {
  @Input()
  set ngVar(context: any) {
    this.context.$implicit = this.context.ngVar = context;
    this.updateView();
  }

  context: any = {};

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

  updateView() {
    this.vcRef.clear();
    this.vcRef.createEmbeddedView(this.templateRef, this.context);
  }
}
Run Code Online (Sandbox Code Playgroud)

使用此*ngVar指令,我们可以使用以下内容

<div *ngVar="false as variable">
      <span>{{variable | json}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

要么

<div *ngVar="false; let variable">
    <span>{{variable | json}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

要么

<div *ngVar="45 as variable">
    <span>{{variable | json}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

要么

<div *ngVar="{ x: 4 } as variable">
    <span>{{variable | json}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

Plunker示例Angular4 ngVar

也可以看看

起源

Angular v4

1)div+ ngIf+let

<div *ngIf="{ a: 1, b: 2 }; let variable">
  <span>{{variable.a}}</span>
  <span>{{variable.b}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

2)div+ ngIf+as

视图

<div *ngIf="{ a: 1, b: 2, c: 3 + x } as variable">
  <span>{{variable.a}}</span>
  <span>{{variable.b}}</span>
  <span>{{variable.c}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

component.ts

export class AppComponent {
  x = 5;
}
Run Code Online (Sandbox Code Playgroud)

3)如果你不想像div你可以使用那样创建包装器ng-container

视图

<ng-container *ngIf="{ a: 1, b: 2, c: 3 + x } as variable">
  <span>{{variable.a}}</span>
  <span>{{variable.b}}</span>
  <span>{{variable.c}}</span>
</ng-container>
Run Code Online (Sandbox Code Playgroud)

  • @Keith感谢您指出这一点.你可以看看我更新的答案 (6认同)
  • 这在大多数情况下都有效,但它不是一般的解决方案,因为它依赖于`变量'是真的 (5认同)
  • 由于 Angular 的命名空间,我不会使用 ngVar。 (4认同)
  • 这应该是新答案,因为它1)比其他解决方案更现代2)总结了当前答案中链接的请求请求,并节省了大量时间3)包括内联示例,而不是外部链接。感谢您展示此内容。AFAIK任何包裹在{{}中的对象都将评估为真实,因此该解决方案非常可靠。 (3认同)
  • 例如,可展开按钮:`* ngIf =“ {Expanded:false} as scope”`,然后,如果您使用引导程序,则可以只使用`[ngClass] =“ {'in':scope.expanded}”`和`(click)=“ scope.expanded =!scope.expanded”`而不是向您的`js` /`ts`文件中添加任何内容。 (3认同)
  • @LeonardoRick您可以指定上下文的类型,类似于 ngIf 指令的做法。`interface VarContext { $implicit: 任意; ngVar:任意;}` https://github.com/angular/angular/blob/21dfb33b2774817f0031c27d88109b03a44950ed/packages/common/src/directives/ng_if.ts#L153 (2认同)

kay*_*tea 67

丑陋,但是:

<div *ngFor="let a of [aVariable]">
  <span>{{a}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

与异步管道一起使用时:

<div *ngFor="let a of [aVariable | async]">
  <span>{{a.prop1}}</span>
  <span>{{a.prop2}}</span>
</div>
Run Code Online (Sandbox Code Playgroud)

  • 对于“*ngFor”,请记住,如果变量值发生更改,所有嵌套内容都将重新创建,直到您指定一个“trackBy”函数,该函数为所有值返回相同的 id。 (5认同)
  • 这是我本能地提出的那个 - 它与`*ngFor ='一起使用[(someStream $ | async).someA]`.我想用``ng-container>`它可以完成工作完全正确! (4认同)

Gün*_*uer 55

更新3

问题2451在Angular 4.0.0中得到修复

也可以看看

更新2

这不受支持.

有模板变量,但不支持分配任意值.它们只能用于指它们被施加到元件,导出指令或组件和范围的变量的名称为类似的结构指示ngFor,

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

更新1

@Directive({
  selector: '[var]',
  exportAs: 'var'
})
class VarDirective {
  @Input() var:any;
}
Run Code Online (Sandbox Code Playgroud)

并初始化它

<div #aVariable="var" var="abc"></div>
Run Code Online (Sandbox Code Playgroud)

要么

<div #aVariable="var" [var]="'abc'"></div>
Run Code Online (Sandbox Code Playgroud)

并使用变量之类的

<div>{{aVariable.var}}</div>
Run Code Online (Sandbox Code Playgroud)

(未测试)

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


Ste*_*ens 55

您可以使用templateAngular 2或ng-templateAngular 4+中的元素在html代码中声明变量.

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

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

<!-- Output
<div>
  <span>123</span>
</div>
-->
Run Code Online (Sandbox Code Playgroud)

您可以使用$implicit上下文对象的属性而不是自定义属性来减少代码量.

<ng-template let-a [ngTemplateOutletContext]="{ $implicit: 123 }" [ngTemplateOutlet]="t" #t>
  <div>
    <span>{{a}}</span>
  </div>
</ng-template>
Run Code Online (Sandbox Code Playgroud)

上下文对象可以是文字对象或任何其他绑定表达式.甚至管道似乎在被括号括起来时也能工作.

有效的例子ngTemplateOutletContext:

  • [ngTemplateOutletContext]="{ aVariable: 123 }"
  • [ngTemplateOutletContext]="{ aVariable: (3.141592 | number:'3.1-5') }"
  • [ngTemplateOutletContext]="{ aVariable: anotherVariable }" 使用 let-a="aVariable"
  • [ngTemplateOutletContext]="{ $implicit: anotherVariable }" 使用 let-a
  • [ngTemplateOutletContext]="ctx"哪里ctx是公共财产

  • 是的,你只能在Angular 2中使用`<template>`.你可以在Angular 4中使用`<template>`或`<ng-template>`,但是你应该只使用`<ng-template>`.Angular 5放弃了对"<template>"的支持. (2认同)
  • 这很奇怪,但它确实有效!Angular 应该通过内置变量指令使这个变得更简单。谢谢。 (2认同)
  • @JohnWhite您是否可能没有添加 `&lt;ng-template #t [ngTemplateOutlet]="t" ...&gt;`?这就是为什么您可能会看到“无法绑定到“ngTemplateOutletContext”,因为它不是已知属性”之类的错误的原因之一。 (2认同)

Abh*_*wat 13

适合我的要求的一个简单的解决方案是:

 <ng-container *ngIf="lineItem.productType as variable">
       {{variable}}
 </ng-container>
Run Code Online (Sandbox Code Playgroud)

或者

 <ng-container *ngIf="'ANY VALUE' as variable">
       {{variable}}
  </ng-container>
Run Code Online (Sandbox Code Playgroud)

我正在使用Angular 版本: 12。看来它也可以与其他版本一起使用。


Aar*_*ron 10

这是我编写的一个指令,它扩展了对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( ) {
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在模板中使用如下:

<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>
Run Code Online (Sandbox Code Playgroud)

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


Phi*_*ohn 10

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

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

组件中的方法可以是这样的

methodName(parameters: any): any {
  return {name: 'Test name'};
}
Run Code Online (Sandbox Code Playgroud)

  • 我知道这已经过时了,但是如果有人正在读这篇文章:不要这样做;不要在模板中编写函数调用(事件除外)。该函数将在每个生命周期执行,因为 Angular 无法检测到变化 (3认同)

Ste*_*aul 9

如果您需要来自 Angular Language Service 的模板中的自动完成支持:

同步:

myVar = { hello: '' };

<ng-container *ngIf="myVar; let var;">
  {{var.hello}}
</ng-container>
Run Code Online (Sandbox Code Playgroud)

使用异步管道:

myVar$ = of({ hello: '' });

<ng-container *ngIf="myVar$ | async; let var;">
  {{var.hello}}
</ng-container>
Run Code Online (Sandbox Code Playgroud)


mon*_*dev 8

我建议这样做:https://medium.com/@AustinMatherne/angular-let-directive-a168d4248138

该指令允许您编写如下内容:

<div *ngLet="'myVal' as myVar">
  <span> {{ myVar }} </span>
</div>
Run Code Online (Sandbox Code Playgroud)

  • 像这样,但 * 保留用于结构指令,这不是,无论如何 +1 (2认同)

De *_*eur 6

使用 Angular 12 :

  <div *ngIf="error$ | async as error">
     <span class="text-warn">{{error.message}}</span>
   </div>
Run Code Online (Sandbox Code Playgroud)


Kee*_*ego 5

我喜欢创建指令来执行此操作的方法(很好的调用@yurzui)。

我最终找到了一篇 Medium 文章Angular“let”指令,它很好地解释了这个问题,并提出了一个自定义的let 指令,该指令最终非常适合我的用例,只需最少的代码更改。

这是我修改后的要点(在发布时):

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

interface LetContext <T> {
  appLet: T | null
}

@Directive({
  selector: '[appLet]',
})
export class LetDirective <T> {
  private _context: LetContext <T> = { appLet: null }

  constructor(_viewContainer: ViewContainerRef, _templateRef: TemplateRef <LetContext <T> >) {
    _viewContainer.createEmbeddedView(_templateRef, this._context)
  }

  @Input()
  set appLet(value: T) {
    this._context.appLet = value
  }
}
Run Code Online (Sandbox Code Playgroud)

我的主要改变是:

  • 将前缀从“ng”更改为“app”(您应该使用应用程序的自定义前缀)
  • 改变appLet: T为appLet: T | null

不知道为什么 Angular 团队不只是制定正式的 ngLet 指令,而是做什么。

原始源代码归功于@AustinMatherne


met*_*152 5

我试图做类似的事情,看起来这已经在新版本的 Angular中修复了。

    <div *ngIf="things.car; let car">
      Nice {{ car }}!
    </div>
    <!-- Nice Honda! -->
Run Code Online (Sandbox Code Playgroud)