Ich bin interessiert zu wissen, was die Anforderung / der Anwendungsfall ist, um den Namen eines Bindungsparameters wie dieses Beispiel ändern zu wollen.
LDJ
29
Es soll nur verhindert werden, dass so etwas wie tab [element] .val nach Instanz wiederholt wird. Ich weiß, dass ich das Problem in der Komponente lösen kann, aber ich habe mir nur angesehen, wie es in der Vorlage zu tun ist (obwohl ich möglicherweise nicht mit dieser Lösung enden kann).
Scipion
2
@LDJ Anwendungsbeispiel: Effizienz. Verwenden Sie das Beispiel von stackblitz.com/angular/… <mat-checkbox [checked] = " descantsAllSelected (node)" [unbestimmt] = "descantsPartiallySelected (node)" (change) = "todoItemSelectionToggle (node)"> {{node. item}} </ mat-checkbox> Tatsächlich ruft die descantsPartiallySelected () descantsAllSelected () auf. Es bedeutet, dass manchmal NachkommenAllSelected zweimal aufgerufen wird. Wenn es eine lokale Variable gibt, kann dies vermieden werden.
Steven.Xi
3
<div *ngIf="{name:'john'} as user1; let user"> <i>{{user1|json}}</i> <i>{{user|json}}</i> </div>
dasfdsa
@dasfdsa Ich glaube user1 === user, also tust du es entweder *ngIf="{name:'john'} as user1oder *ngIf="{name:'john'};let userwie in Yurzuis Antwort .
CPHPython
Antworten:
168
Aktualisieren
Wir können einfach eine Direktive wie erstellen *ngIfund sie nennen*ngVar
Dies wird in den meisten Fällen funktionieren, aber es ist keine allgemeine Lösung, da es darauf beruht variable, wahr zu sein
Keith
6
@ Keith Danke, dass du darauf hingewiesen hast. Sie können einen Blick auf meine aktualisierte Antwort
werfen
3
Dies sollte die neue Antwort sein, da sie 1) moderner als die andere Lösung ist 2) die in der aktuellen Antwort verknüpften Pull-Anforderungen zusammenfasst und viel Zeit spart 3) die Beispiele inline und nicht über einen externen Link enthält. Danke, dass du das gezeigt hast. AFAIK jedes eingewickelte Objekt {}wird als wahr bewertet, daher ist diese Lösung ziemlich robust.
Kvanberendonck
4
Zum Beispiel erweiterbare Schaltflächen: *ngIf="{ expanded: false } as scope"Wenn Sie dann Bootstrap verwenden, können Sie einfach verwenden [ngClass]="{ 'in': scope.expanded }"und (click)="scope.expanded = !scope.expanded"anstatt etwas zu Ihren js/ tsDateien hinzuzufügen .
Kvanberendonck
1
verwandtes Github-Problem (weist darauf hin, dass ein einfaches *ngIfanstelle eines benutzerdefinierten Ngvar-Materials verwendet wird): github.com/angular/angular/issues/14985
phil294
79
Hässlich, aber:
<div *ngFor="let a of [aVariable]"><span>{{a}}</span></div>
Bei Verwendung mit asynchroner Pipe:
<div *ngFor="let a of [aVariable | async]"><span>{{a.prop1}}</span><span>{{a.prop2}}</span></div>
Das habe ich mir instinktiv ausgedacht - es funktioniert *ngFor="let a of [(someStream$ | async).someA]auch. Ich denke, mit einem verwendet <ng-container>es den Job ganz richtig!
Angelos Pikoulas
1
*ngForBeachten Sie in diesem Fall , dass der gesamte verschachtelte Inhalt neu erstellt wird, wenn sich der Variablenwert ändert, bis Sie eine trackByFunktion angeben , die für alle Werte dieselbe ID zurückgibt.
Valeriy Katkov
72
Sie können Variablen in HTML-Code deklarieren, indem Sie ein templateElement in Angular 2 oder verwendenng-template Angular 4+ verwenden.
Vorlagen haben ein Kontextobjekt, dessen Eigenschaften Variablen mithilfe der letBindungssyntax zugewiesen werden können . Beachten Sie, dass Sie einen Ausgang für die Vorlage angeben müssen, dieser kann jedoch ein Verweis auf sich selbst sein.
Das Kontextobjekt kann ein Literalobjekt oder ein anderer Bindungsausdruck sein. Sogar Rohre scheinen zu funktionieren, wenn sie von Klammern umgeben sind.
Damit es funktioniert, musste ich Ihren Code von '<template ...' in '<ng-template ...' ändern.
Humppakäräjät
2
Ja, Sie können nur <template>in Angular 2 verwenden. Sie können entweder <template>oder <ng-template>in Angular 4 verwenden, aber Sie sollten nur verwenden <ng-template>. Winkel 5 fallen gelassen für <template>.
Steven Liekens
Wofür ist das t?
Matttm
1
@matttm #tist eine Vorlagenvariable, in der die gespeichert wird ng-template. Es wird verwendet [ngTemplateOutlet]="t", um die ng-Template-Referenz selbst zu erstellen.
Steven Liekens
Das ist bizarr, aber es funktioniert! Angular sollte dies mit einer integrierten Variablenanweisung vereinfachen. Vielen Dank.
Es gibt Vorlagenvariablen, aber es wird nicht unterstützt, beliebige Werte zuzuweisen. Sie können nur verwendet werden, um auf die Elemente zu verweisen, auf die sie angewendet werden, exportierte Namen von Direktiven oder Komponenten und Bereichsvariablen für strukturelle Direktiven wiengFor ,
Wäre es nicht möglich, eine strukturelle Richtlinie dafür zu erstellen?
Scipion
Wenn Sie dies wiederholt benötigen, kann eine Direktive das tun, was Sie wollen. Eine strukturelle Richtlinie schafft eine eigene Ansicht, das ist wahrscheinlich nicht das, was Sie wollen.
Günter Zöchbauer
1
@ GünterZöchbauer, sehr gutes Zeug. Ich weiß, dass es wahrscheinlich besser ist, Variablen in der component.tsDatei berechnen / vorbereiten zu lassen . Aufgrund eines Synchronisierungsschemas, das ich in meiner App implementiere, ist es für mich in einigen Fällen viel einfacher, sie in der Ansicht zu haben. Ich nutze die Javascript-Referenzregeln, wenn verschiedene Variablen auf dasselbe Objekt verweisen.
AmmarCSE
Ich bekomme einen Fehler wie There is no directive with "exportAs" set to "var". Kann mir bitte jemand sagen, welchen Fehler ich gemacht habe? Ich habe die obige Richtlinie verwendet.
Partha Sarathi Ghosh
Vielleicht haben Sie die Direktive declarations: [...]von nicht hinzugefügt @NgModule(). Wenn dies nicht das Problem ist, erstellen Sie bitte eine neue Frage und geben Sie den Code an, mit dem das Problem diagnostiziert werden kann.
Günter Zöchbauer
11
Hier ist eine Direktive, die ich geschrieben habe und die die Verwendung des exportAs decorator-Parameters erweitert und es Ihnen ermöglicht, ein Wörterbuch als lokale Variable zu verwenden.
import{Directive,Input}from"@angular/core";@Directive({
selector:"[localVariables]",
exportAs:"localVariables"})exportclassLocalVariables{@Input("localVariables")set localVariables(struct: any ){if(typeofstruct==="object"){for(var variableName instruct){this[variableName]=struct[variableName];}}}constructor(){}}
Sie können es wie folgt in einer Vorlage verwenden:
Übergibt einen 'Production'-Build nicht wie er ist (wird auch von IDEs als Fehler angezeigt). In [key: string]: any;auf die Classdieses zu erhalten , um.
so, aber * ist für strukturelle Richtlinien reserviert, die dies sowieso nicht ist +1
danday74
7
Wenn Sie die Antwort einer Funktion abrufen und in eine Variable umwandeln möchten, können Sie sie wie folgt in der Vorlage verwenden ng-container, um Änderungen an der Vorlage zu vermeiden.
<ng-container *ngIf="methodName(parameters) as respObject">
{{respObject.name}}
</ng-container>
Und die Methode in der Komponente kann so etwas wie sein
methodName(parameters: any): any {return{name:'Test name'};}
@Amirreza, um genau zu sein, verwende ich ElementRef, um einen Wert vorübergehend zu speichern.
Jack Rus
Genial! Ich musste verwenden, "?"weil ich die Meldung "Bezeichner 'Wert' ist nicht definiert" wie folgt hatte => "offen? .Wert" Aber es funktioniert !!
A. Morel
2
Ich verwende Angular 6x und habe am Ende das folgende Snippet verwendet. Ich habe ein Szenario, in dem ich Benutzer aus einem Aufgabenobjekt finden muss. Es enthält eine Reihe von Benutzern, aber ich muss den zugewiesenen Benutzer auswählen.
Ich mochte den Ansatz, eine Direktive zu erstellen, um dies zu tun (guter Ruf @yurzui).
Am Ende fand ich eine mittlere Artikel- Angular-Let-Direktive, die dieses Problem gut erklärt und eine benutzerdefinierte Let-Direktive vorschlägt , die für meinen Anwendungsfall mit minimalen Codeänderungen hervorragend funktioniert.
Hier ist das Wesentliche (zum Zeitpunkt der Veröffentlichung) mit meinen Änderungen:
Beachten Sie für diejenigen, die sich entschieden haben, eine strukturelle Direktive als Ersatz für zu verwenden *ngIf, dass der Kontext der Direktive nicht standardmäßig typgeprüft ist. Informationen zum Erstellen einer typsicheren Direktiveneigenschaft ngTemplateContextGuardfinden Sie unter Typisieren des Kontextes der Direktive . Beispielsweise:
import{Directive,Input,TemplateRef,ViewContainerRef}from'@angular/core';@Directive({// don't use 'ng' prefix since it's reserved for Angular
selector:'[appVar]',})exportclassVarDirective<T = unknown>{// https://angular.io/guide/structural-directives#typing-the-directives-contextstatic ngTemplateContextGuard<T>(dir:VarDirective<T>, ctx: any): ctx is Context<T>{returntrue;}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);}}}interfaceContext<T>{
appVar: T;}
Die Direktive kann genauso verwendet werden *ngIf, außer dass sie falsche Werte speichern kann :
<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>
Der einzige Nachteil im Vergleich dazu *ngIfist, dass Angular Language Service den Variablentyp nicht ermitteln kann, sodass die Vorlagen keinen Code vervollständigen. Ich hoffe es wird bald behoben.
<div *ngIf="{name:'john'} as user1; let user"> <i>{{user1|json}}</i> <i>{{user|json}}</i> </div>
user1 === user
, also tust du es entweder*ngIf="{name:'john'} as user1
oder*ngIf="{name:'john'};let user
wie in Yurzuis Antwort .Antworten:
Aktualisieren
Wir können einfach eine Direktive wie erstellen
*ngIf
und sie nennen*ngVar
ng-var.directive.ts
Mit dieser
*ngVar
Richtlinie können wir Folgendes verwendenoder
oder
oder
Plunker Beispiel Angular4 ngVar
Siehe auch
Ursprüngliche Antwort
Winkel v4
1)
div
+ngIf
+let
2)
div
+ngIf
+as
Aussicht
component.ts
3) Wenn Sie keinen Wrapper erstellen möchten, wie
div
Sie ihn verwenden könnenng-container
Aussicht
Wie @Keith in den Kommentaren erwähnt
Siehe Update für einen anderen Ansatz.
quelle
variable
, wahr zu sein{}
wird als wahr bewertet, daher ist diese Lösung ziemlich robust.*ngIf="{ expanded: false } as scope"
Wenn Sie dann Bootstrap verwenden, können Sie einfach verwenden[ngClass]="{ 'in': scope.expanded }"
und(click)="scope.expanded = !scope.expanded"
anstatt etwas zu Ihrenjs
/ts
Dateien hinzuzufügen .*ngIf
anstelle eines benutzerdefinierten Ngvar-Materials verwendet wird): github.com/angular/angular/issues/14985Hässlich, aber:
Bei Verwendung mit asynchroner Pipe:
quelle
*ngFor="let a of [(someStream$ | async).someA]
auch. Ich denke, mit einem verwendet<ng-container>
es den Job ganz richtig!*ngFor
Beachten Sie in diesem Fall , dass der gesamte verschachtelte Inhalt neu erstellt wird, wenn sich der Variablenwert ändert, bis Sie einetrackBy
Funktion angeben , die für alle Werte dieselbe ID zurückgibt.Sie können Variablen in HTML-Code deklarieren, indem Sie ein
template
Element in Angular 2 oder verwendenng-template
Angular 4+ verwenden.Vorlagen haben ein Kontextobjekt, dessen Eigenschaften Variablen mithilfe der
let
Bindungssyntax zugewiesen werden können . Beachten Sie, dass Sie einen Ausgang für die Vorlage angeben müssen, dieser kann jedoch ein Verweis auf sich selbst sein.Sie können die Codemenge reduzieren, indem Sie die
$implicit
Eigenschaft des Kontextobjekts anstelle einer benutzerdefinierten Eigenschaft verwenden.Das Kontextobjekt kann ein Literalobjekt oder ein anderer Bindungsausdruck sein. Sogar Rohre scheinen zu funktionieren, wenn sie von Klammern umgeben sind.
Gültige Beispiele für
ngTemplateOutletContext
:[ngTemplateOutletContext]="{ aVariable: 123 }"
[ngTemplateOutletContext]="{ aVariable: (3.141592 | number:'3.1-5') }"
[ngTemplateOutletContext]="{ aVariable: anotherVariable }"
benutzen mitlet-a="aVariable"
[ngTemplateOutletContext]="{ $implicit: anotherVariable }"
benutzen mitlet-a
[ngTemplateOutletContext]="ctx"
Woctx
ist ein öffentliches Eigentumquelle
<template>
in Angular 2 verwenden. Sie können entweder<template>
oder<ng-template>
in Angular 4 verwenden, aber Sie sollten nur verwenden<ng-template>
. Winkel 5 fallen gelassen für<template>
.t
?#t
ist eine Vorlagenvariable, in der die gespeichert wirdng-template
. Es wird verwendet[ngTemplateOutlet]="t"
, um die ng-Template-Referenz selbst zu erstellen.Update 3
Problem 2451 wurde in Angular 4.0.0 behoben
Siehe auch
Update 2
Dies wird nicht unterstützt.
Es gibt Vorlagenvariablen, aber es wird nicht unterstützt, beliebige Werte zuzuweisen. Sie können nur verwendet werden, um auf die Elemente zu verweisen, auf die sie angewendet werden, exportierte Namen von Direktiven oder Komponenten und Bereichsvariablen für strukturelle Direktiven wie
ngFor
,Siehe auch https://github.com/angular/angular/issues/2451
Update 1
und initialisiere es wie
oder
und benutze die Variable wie
(nicht getestet)
#aVariable
erstellt einen Verweis auf dieVarDirective
(exportAs: 'var'
)var="abc"
instanziiert dieVarDirective
und übergibt den Zeichenfolgenwert"abc"
an seine Werteingabe.aVariable.var
liest den Wert, der der Eingabe dervar
Direktiven zugewiesen istvar
.quelle
component.ts
Datei berechnen / vorbereiten zu lassen . Aufgrund eines Synchronisierungsschemas, das ich in meiner App implementiere, ist es für mich in einigen Fällen viel einfacher, sie in der Ansicht zu haben. Ich nutze die Javascript-Referenzregeln, wenn verschiedene Variablen auf dasselbe Objekt verweisen.There is no directive with "exportAs" set to "var"
. Kann mir bitte jemand sagen, welchen Fehler ich gemacht habe? Ich habe die obige Richtlinie verwendet.declarations: [...]
von nicht hinzugefügt@NgModule()
. Wenn dies nicht das Problem ist, erstellen Sie bitte eine neue Frage und geben Sie den Code an, mit dem das Problem diagnostiziert werden kann.Hier ist eine Direktive, die ich geschrieben habe und die die Verwendung des exportAs decorator-Parameters erweitert und es Ihnen ermöglicht, ein Wörterbuch als lokale Variable zu verwenden.
Sie können es wie folgt in einer Vorlage verwenden:
Natürlich kann #local ein beliebiger gültiger lokaler Variablenname sein.
quelle
[key: string]: any;
auf dieClass
dieses zu erhalten , um.Ich würde dies vorschlagen: https://medium.com/@AustinMatherne/angular-let-directive-a168d4248138
Mit dieser Anweisung können Sie Folgendes schreiben:
quelle
Wenn Sie die Antwort einer Funktion abrufen und in eine Variable umwandeln möchten, können Sie sie wie folgt in der Vorlage verwenden
ng-container
, um Änderungen an der Vorlage zu vermeiden.Und die Methode in der Komponente kann so etwas wie sein
quelle
Wenn Sie Unterstützung für die automatische Vervollständigung von innen in Ihren Vorlagen vom Angular Language Service benötigen :
Synchron:
Verwenden einer asynchronen Pipe:
quelle
Es ist viel einfacher, es ist nichts zusätzliches erforderlich. In meinem Beispiel deklariere ich die Variable "open" und verwende sie dann.
quelle
"?"
weil ich die Meldung "Bezeichner 'Wert' ist nicht definiert" wie folgt hatte => "offen? .Wert" Aber es funktioniert !!Ich verwende Angular 6x und habe am Ende das folgende Snippet verwendet. Ich habe ein Szenario, in dem ich Benutzer aus einem Aufgabenobjekt finden muss. Es enthält eine Reihe von Benutzern, aber ich muss den zugewiesenen Benutzer auswählen.
quelle
Ich mochte den Ansatz, eine Direktive zu erstellen, um dies zu tun (guter Ruf @yurzui).
Am Ende fand ich eine mittlere Artikel- Angular-Let-Direktive, die dieses Problem gut erklärt und eine benutzerdefinierte Let-Direktive vorschlägt , die für meinen Anwendungsfall mit minimalen Codeänderungen hervorragend funktioniert.
Hier ist das Wesentliche (zum Zeitpunkt der Veröffentlichung) mit meinen Änderungen:
Meine wichtigsten Änderungen waren:
appLet: T
zuappLet: T | null
Ich bin mir nicht sicher, warum das Angular-Team nicht nur eine offizielle ngLet-Direktive erlassen hat, sondern was auch immer.
Das ursprüngliche Quellcode-Guthaben geht an @AustinMatherne
quelle
Kurze Antwort, die jemandem hilft
* Sie können jedoch ViewChild Decorator verwenden, um in Ihrer Komponente darauf zu verweisen.
Referenz firstNameInput-Variable in Component
Danach können Sie this.nameInputRef an einer beliebigen Stelle in Ihrer Komponente verwenden.
Arbeiten mit ng-template
Im Fall von ng-template ist dies etwas anders, da jede Vorlage ihre eigenen Eingabevariablen hat.
https://stackblitz.com/edit/angular-2-template-reference-variable
quelle
Beachten Sie für diejenigen, die sich entschieden haben, eine strukturelle Direktive als Ersatz für zu verwenden
*ngIf
, dass der Kontext der Direktive nicht standardmäßig typgeprüft ist. Informationen zum Erstellen einer typsicheren DirektiveneigenschaftngTemplateContextGuard
finden Sie unter Typisieren des Kontextes der Direktive . Beispielsweise:Die Direktive kann genauso verwendet werden
*ngIf
, außer dass sie falsche Werte speichern kann :Der einzige Nachteil im Vergleich dazu
*ngIf
ist, dass Angular Language Service den Variablentyp nicht ermitteln kann, sodass die Vorlagen keinen Code vervollständigen. Ich hoffe es wird bald behoben.quelle