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

时间:2016-07-26 06:16:59

标签: html angular

我有以下模板:

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

并希望最终:

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

有办法吗?

15 个答案:

答案 0 :(得分:98)

更新

正如@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);
  }
}

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

<div *ngVar="false as variable">
      <span>{{variable | json}}</span>
</div>

<div *ngVar="false; let variable">
    <span>{{variable | json}}</span>
</div>

<div *ngVar="45 as variable">
    <span>{{variable | json}}</span>
</div>

<div *ngVar="{ x: 4 } as variable">
    <span>{{variable | json}}</span>
</div>

<强> Plunker Example 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>

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>

<强> component.ts

export class AppComponent {
  x = 5;
}

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>

答案 1 :(得分:55)

丑陋,但是:

<div *ngFor="let a of [aVariable]">
  <span>{{a}}</span>
</div>

与异步管道一起使用时:

<div *ngFor="let a of [aVariable | async]">
  <span>{{a.prop1}}</span>
  <span>{{a.prop2}}</span>
</div>

答案 2 :(得分:49)

更新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;
}

并将其初始化为

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

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

并使用像

这样的变量
<div>{{aVariable.var}}</div>

(未经测试)

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

答案 3 :(得分:36)

您可以使用Angular 2中的"C:\Program Files (x86)\Java\jdk1.7.0_80\bin\java" -classpath "C:\Program Files (x86)\Java\jdk1.7.0_80\lib\tools.jar" -Dhttps.protocols=TLSv1.2 com.sun.tools.internal.ws.WsImport -keep -verbose https://<server-name>/Test/Test/Transform?wsdl 元素或Angular 4 +中的template来声明html代码中的变量。

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

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> --> 属性而不是自定义属性来减少代码量。

$implicit

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

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

  • 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"是公共财产

答案 4 :(得分:8)

这是我编写的一个指令,它扩展了对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可以是任何有效的本地变量名。

答案 5 :(得分:7)

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

同步:

myVar = { hello: '' };

<ng-container *ngIf="myVar; let var;">
  {{var.hello}}
</ng-container>

使用异步管道:

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

<ng-container *ngIf="myVar$ | async; let var;">
  {{var.hello}}
</ng-container>

答案 6 :(得分:6)

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

该指令允许您编写类似:

的内容
<div *ngLet="'myVal' as myVar">
  <span> {{ myVar }} </span>
</div>

答案 7 :(得分:2)

它更简单,不需要任何额外的东西。在我的例子中,我声明变量“open”然后使用它。

   <mat-accordion class="accord-align" #open>
      <mat-expansion-panel hideToggle="true" (opened)="open.value=true" (closed)="open.value=false">
        <mat-expansion-panel-header>
          <span class="accord-title">Review Policy Summary</span>
          <span class="spacer"></span>
          <a *ngIf="!open.value" class="f-accent">SHOW</a>
          <a *ngIf="open.value" class="f-accent">HIDE</a>
        </mat-expansion-panel-header>
        <mat-divider></mat-divider>
        <!-- Quote Details Component -->
        <quote-details [quote]="quote"></quote-details>
      </mat-expansion-panel>
    </mat-accordion>

答案 8 :(得分:1)

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

<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>

答案 9 :(得分:1)

对某人有帮助的简短答案

  • 模板引用变量通常引用一个 模板。
  • 还引用了angular或web组件和指令。
  • 这意味着您可以轻松地访问模板中任意位置的变量

enter image description here

enter image description here

  • 使用哈希符号(#)声明参考变量
  • 能够在事件中将变量作为参数传递

enter image description here

  show(lastName: HTMLInputElement){
    this.fullName = this.nameInputRef.nativeElement.value + ' ' + lastName.value;
    this.ctx.fullName = this.fullName;
  }

*但是,您可以使用ViewChild装饰器在组件内部对其进行引用。

import {ViewChild, ElementRef} from '@angular/core';

在组件内部引用firstNameInput变量

@ViewChild('firstNameInput') nameInputRef: ElementRef;

之后,您可以在组件内部的任何地方使用this.nameInputRef。

使用ng-template

对于ng-template,它有点不同,因为每个模板都有自己的输入变量集。

enter image description here

https://stackblitz.com/edit/angular-2-template-reference-variable

答案 10 :(得分:1)

对于那些决定使用结构指令代替*ngIf的用户,请记住,默认情况下不对指令上下文进行类型检查。要创建类型安全指令ngTemplateContextGuard属性,请参见Typing the directive's context。例如:

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一样使用,除了它可以存储 false 值:

<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 Language Service无法确定变量类型,因此模板中没有代码完成。我希望它将尽快修复。

答案 11 :(得分:1)

适用于我的要求的简单解决方案是:

 <ng-container *ngIf="lineItem.productType as variable">
       {{variable}}
 </ng-container>

 <ng-container *ngIf="'ANY VALUE' as variable">
       {{variable}}
  </ng-container>

我正在使用 Angular 版本:12。它似乎也适用于其他版本。

答案 12 :(得分:0)

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

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

组件中的方法可能类似于

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

答案 13 :(得分:0)

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

我最终找到了一篇中型文章Angular "let" Directive,该文章很好地解释了这个问题,并提出了一个自定义let directive,该文章最终以最小的代码更改就非常适合我的用例。

以下是我的修改要点(发布时):

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
  }
}

我的主要更改是:

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

不确定为什么Angular团队不仅制定了正式的ngLet指令,还制定了什么。

原始源代码归功于@AustinMatherne

答案 14 :(得分:0)

@yurzui的

原始答案由于-strange problem migrating angular 8 app to 9而无法从Angular 9开始。 但是,您仍然可以通过使用 ngVar 指令并从中使用它来受益

import functools


def print_name2(f):
    @functools.wraps(f)
    def wrapper(*args, **kwargs):
        print('2: {} has been revoked'.format(f.__name__))
        return f(*args, **kwargs)
    return wrapper


def print_name3(f):
    print('3: {} has been revoked'.format(f.__name__))
    return f


@print_name3
def my_str(i):
    return str(i)


@print_name2
def my_str2(i):
    return str(i)

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