我有以下模板:
<div>
<span>{{aVariable}}</span>
</div>
并希望最终:
<div "let a = aVariable">
<span>{{a}}</span>
</div>
有办法吗?
答案 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
创建对VarDirective
(exportAs: '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)
对某人有帮助的简短答案
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,它有点不同,因为每个模板都有自己的输入变量集。
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
}
}
我的主要更改是:
appLet: T
更改为appLet: T | null
不确定为什么Angular团队不仅制定了正式的ngLet指令,还制定了什么。
原始源代码归功于@AustinMatherne
答案 14 :(得分:0)
原始答案由于-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警告:“ 变量未定义”