Подтвердить что ты не робот

Как объявить переменную в шаблоне в Angular

У меня есть следующий шаблон:

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

и хотел бы получить:

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

Есть ли способ сделать?

4b9b3361

Ответ 1

обновление 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.

Ответ 2

Update

Как @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>

Ответ 3

Ужасно, но:

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

Ответ 4

Вы можете объявить переменные в 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 является публичной собственностью

Ответ 5

Вот директива, которую я написал, которая расширяет использование параметра 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 может быть любым допустимым именем локальной переменной.

Ответ 7

Это намного проще, не нужно ничего дополнительного. В моем примере я объявляю переменную "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

В случае, если вы хотите получить ответ функции и установить его в переменную, вы можете использовать его, как показано ниже в шаблоне, используя ng-container, чтобы избежать изменения шаблона.

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

И метод в компоненте может быть что-то вроде

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

Ответ 9

Я использую 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>

Ответ 10

Краткий ответ, который поможет кому-то

  • Ссылочная переменная шаблона часто ссылается на элемент DOM внутри шаблон.
  • Также ссылка на angular или веб-компонент и директива.
  • Это означает, что вы можете легко получить доступ к переменной в любом месте шаблона

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-шаблоном

В случае ng-template он немного отличается, потому что каждый шаблон имеет свой собственный набор входных переменных.

enter image description here

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

Ответ 11

Мне понравился подход к созданию директивы для этого (хороший вызов @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
  }
}

Моими основными изменениями были:

  • изменение префикса с "ng" на "приложение" (вы должны использовать любой префикс вашего приложения)
  • изменение appLet: T на appLet: T | null

Не уверен, почему команда Angular выпустила не только официальную директиву ngLet, но и другие.

Оригинальный кредит исходного кода идет к @AustinMatherne