У меня есть следующий шаблон:
<div>
<span>{{aVariable}}</span>
</div>
и хотел бы получить:
<div "let a = aVariable">
<span>{{a}}</span>
</div>
Есть ли способ сделать?
У меня есть следующий шаблон:
<div>
<span>{{aVariable}}</span>
</div>
и хотел бы получить:
<div "let a = aVariable">
<span>{{a}}</span>
</div>
Есть ли способ сделать?
обновление 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
.Как @Keith упоминается в комментариях
это будет работать в большинстве случаев, но это не общее решение, так как оно полагается на переменную, являющуюся правдивой
Так что исходный ответ работает как @Keith. Вот еще один подход. Мы можем просто создать директиву как *ngIf
и называть ее *ngVar
нг-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>
Пример плунжера 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>
Ужасно, но:
<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>
Вы можете объявить переменные в HTML-коде, используя элемент template
в Angular 2 или ng-template
в Angular 4+.
Шаблоны имеют объект контекста, свойства которого можно назначать переменным с использованием синтаксиса привязки 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>
Объект контекста может быть литеральным объектом или любым другим выражением привязки. Кажется, даже pipes работают в круглых скобках.
Допустимые примеры 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
является публичной собственностьюВот директива, которую я написал, которая расширяет использование параметра decorAs 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 может быть любым допустимым именем локальной переменной.
Я бы предложил это: https://medium.com/@AustinMatherne/angular-let-directive-a168d4248138
Эта директива позволяет вам написать что-то вроде:
<div *ngLet="'myVal' as myVar">
<span> {{ myVar }} </span>
</div>
Это намного проще, не нужно ничего дополнительного. В моем примере я объявляю переменную "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>
В случае, если вы хотите получить ответ функции и установить его в переменную, вы можете использовать его, как показано ниже в шаблоне, используя ng-container
, чтобы избежать изменения шаблона.
<ng-container *ngIf="methodName(parameters) as respObject">
{{respObject.name}}
</ng-container>
И метод в компоненте может быть что-то вроде
methodName(parameters: any): any {
return {name: 'Test name'};
}
Я использую angular 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>
Краткий ответ, который поможет кому-то
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-шаблоном
В случае ng-template он немного отличается, потому что каждый шаблон имеет свой собственный набор входных переменных.
https://stackblitz.com/edit/angular-2-template-reference-variable
Мне понравился подход к созданию директивы для этого (хороший вызов @yurzui).
Я закончил тем, что нашел статью 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
}
}
Моими основными изменениями были:
appLet: T
на appLet: T | null
Не уверен, почему команда Angular выпустила не только официальную директиву ngLet, но и другие.
Оригинальный кредит исходного кода идет к @AustinMatherne