Je suis intéressé de savoir quelle est l'exigence / cas d'utilisation pour vouloir changer le nom d'un paramètre de liaison tel que cet exemple?
LDJ
31
C'est juste pour éviter de répéter quelque chose comme tab [élément] .val par instance. Je sais que je peux résoudre le problème dans le composant, mais je cherchais juste comment faire dans le modèle (même si je ne peux pas me retrouver avec cette solution).
Scipion
2
@LDJ un exemple d'utilisation: l'efficacité. Utilisez l'exemple de stackblitz.com/angular/... <mat-checkbox [checked] = "descendantsAllSelected (node)" [indeterminate] = "descendantsPartiallySelected (node)" (change) = "todoItemSelectionToggle (node)"> {{node. item}} </mat-checkbox> en fait les descendantsPartiallySelected () appelle descendantsAllSelected (). Cela signifie que parfois descendantsAllSelected est appelé deux fois. S'il y a une variable locale, cela peut être évité.
Steven.Xi
3
<div *ngIf="{name:'john'} as user1; let user"> <i>{{user1|json}}</i> <i>{{user|json}}</i> </div>
dasfdsa
@dasfdsa je crois user1 === user, donc vous faites *ngIf="{name:'john'} as user1ou *ngIf="{name:'john'};let usercomme dans la réponse de yurzui .
CPHPython
Réponses:
175
Mettre à jour
Nous pouvons simplement créer une directive comme *ngIfet l'appeler*ngVar
cela fonctionnera dans la plupart des cas, mais ce n'est pas une solution générale car elle repose sur la variablevérité
Keith
6
@Keith Merci de l'avoir signalé. Vous pouvez jeter un oeil à ma réponse mise à jour
yurzui
3
Cela devrait être la nouvelle réponse car elle 1) est plus moderne que l'autre solution 2) résume les pull requests liées dans la réponse actuelle et fait gagner beaucoup de temps 3) inclut les exemples en ligne plutôt que par lien externe. Merci de l'avoir montré. AFAIK tout objet enveloppé {}évaluera à la vérité, donc cette solution est assez robuste.
kvanberendonck
4
Par exemple, des boutons extensibles: *ngIf="{ expanded: false } as scope"et ensuite, si vous utilisez bootstrap, vous pouvez simplement utiliser [ngClass]="{ 'in': scope.expanded }"et (click)="scope.expanded = !scope.expanded"au lieu d'ajouter quoi que ce soit à vos fichiers js/ ts.
C'est celui que j'ai inventé instinctivement - cela fonctionne *ngFor="let a of [(someStream$ | async).someA]aussi. Je suppose qu'utilisé avec un <ng-container>il sert parfaitement le travail!
Angelos Pikoulas
2
Dans le cas de *ngFor, gardez à l'esprit que tout le contenu imbriqué sera recréé si la valeur de la variable change, jusqu'à ce que vous spécifiiez une trackByfonction qui renvoie le même identifiant pour toutes les valeurs.
Valeriy Katkov le
76
Vous pouvez déclarer des variables en code html en utilisant un templateélément dans Angular 2 ou ng-templatedans Angular 4+.
Les modèles ont un objet de contexte dont les propriétés peuvent être affectées à des variables à l'aide de letla syntaxe de liaison. Notez que vous devez spécifier une sortie pour le modèle, mais cela peut être une référence à lui-même.
L'objet de contexte peut être un objet littéral ou toute autre expression de liaison. Même les tuyaux semblent fonctionner lorsqu'ils sont entourés de parenthèses.
Pour que cela fonctionne, j'ai dû changer votre code de «<template ...» à «<ng-template ...».
Humppakäräjät
2
Oui, vous ne pouvez utiliser que <template>dans Angular 2. Vous pouvez utiliser soit<template> ou l' ou <ng-template>dans Angular 4, mais vous ne devez utiliser que <ng-template>. Angular 5 a abandonné le support pour <template>.
Steven Liekens
Quel est le tpour?
matttm
1
@matttm #test une variable de modèle qui stocke le fichier ng-template. Il est utilisé dans[ngTemplateOutlet]="t" pour créer la référence ng-template elle-même.
Steven Liekens
C'est bizare, mais ça marche! Angular devrait rendre cela plus simple, avec une directive de variable intégrée. Merci.
Il existe des variables de modèle mais il n'est pas pris en charge pour attribuer des valeurs arbitraires. Ils ne peuvent être utilisés que pour faire référence aux éléments auxquels ils sont appliqués, aux noms exportés de directives ou de composants et aux variables de portée pour les directives structurelles telles quengFor ,
Ne serait-il pas possible de créer une directive structurelle pour ce faire?
Scipion
Si vous en avez besoin à plusieurs reprises, une directive peut faire ce que vous voulez. Une directive structurelle crée sa propre vue, ce n'est probablement pas ce que vous voulez.
Günter Zöchbauer
1
@ GünterZöchbauer, de très bonnes choses. Je sais que c'est probablement une meilleure pratique d'avoir des variables calculées / préparées dans le component.tsfichier. Mais c'est tellement plus facile pour moi de les avoir dans la vue dans certains cas en raison d'un schéma de synchronisation que j'implémente dans mon application. Je profite des règles de référence javascript lorsque différentes variables pointent vers le même objet.
AmmarCSE
Je reçois une erreur comme There is no directive with "exportAs" set to "var". Quelqu'un peut-il me dire quelle erreur j'ai fait? J'ai utilisé la directive ci-dessus.
Partha Sarathi Ghosh
Peut-être n'avez-vous pas ajouté la directive à declarations: [...]of @NgModule(). Si ce n'est pas le problème, veuillez créer une nouvelle question et fournir le code qui permet de diagnostiquer le problème.
comme ça mais * est réservé aux directives structurelles ce qui n'est pas, de toute façon +1
danday74
11
Voici une directive que j'ai écrite qui développe l'utilisation du paramètre de décorateur exportAs, et vous permet d'utiliser un dictionnaire comme variable locale.
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(){}}
Ne passe pas une construction de «production» telle quelle (apparaît également comme des erreurs par les IDE). Ajoutez [key: string]: any;à la Classpour contourner ce problème.
Charly le
7
Si vous souhaitez obtenir la réponse d'une fonction et la définir dans une variable, vous pouvez l'utiliser comme suit dans le modèle, en utilisant ng-containerpour éviter de modifier le modèle.
<ng-container *ngIf="methodName(parameters) as respObject">
{{respObject.name}}
</ng-container>
Et la méthode dans le composant peut être quelque chose comme
methodName(parameters: any): any {return{name:'Test name'};}
J'utilise angular 6x et j'ai fini par utiliser l'extrait ci-dessous. J'ai un scénario où je dois trouver un utilisateur à partir d'un objet de tâche. il contient un tableau d'utilisateurs mais je dois choisir l'utilisateur assigné.
vous nommez une balise, ce n'est pas une déclaration de variable
Amirreza
1
@Amirreza, pour être précis, j'utilise ElementRef pour stocker temporairement une valeur.
Jack Rus
Impressionnant! J'ai dû utiliser "?"parce que j'avais le message "L'identifiant 'valeur' n'est pas défini" comme ça => "open? .Value" Mais ça marche !!
A. Morel
1
J'ai aimé l'approche consistant à créer une directive pour ce faire (bon appel @yurzui).
J'ai fini par trouver un article Medium Directive "let" angulaire qui explique bien ce problème et propose une directive let personnalisée qui a fonctionné très bien pour mon cas d'utilisation avec des changements de code minimes.
Voici l'essentiel (au moment de la publication) avec mes modifications:
Pour ceux qui ont décidé d'utiliser une directive structurelle en remplacement de *ngIf, gardez à l'esprit que le contexte de la directive n'est pas de type vérifié par défaut. Pour créer une ngTemplateContextGuardpropriété de directive de type sécurisé , vous devez ajouter, voir Saisie du contexte de la directive . Par exemple:
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;}
La directive peut être utilisée comme *ngIf, sauf qu'elle peut stocker de fausses valeurs:
<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>
Le seul inconvénient par rapport à *ngIfest que Angular Language Service ne peut pas déterminer le type de variable, il n'y a donc pas de complétion de code dans les modèles. J'espère que cela sera corrigé bientôt.
<div *ngIf="{name:'john'} as user1; let user"> <i>{{user1|json}}</i> <i>{{user|json}}</i> </div>
user1 === user
, donc vous faites*ngIf="{name:'john'} as user1
ou*ngIf="{name:'john'};let user
comme dans la réponse de yurzui .Réponses:
Mettre à jour
Nous pouvons simplement créer une directive comme
*ngIf
et l'appeler*ngVar
ng-var.directive.ts
avec cette
*ngVar
directive, nous pouvons utiliser ce qui suitou
ou
ou
Exemple de Plunker Angular4 ngVar
Voir également
Réponse originale
Angulaire v4
1)
div
+ngIf
+let
2)
div
+ngIf
+as
vue
component.ts
3) Si vous ne voulez pas créer de wrapper comme
div
vous pouvez utiliserng-container
vue
Comme @Keith l'a mentionné dans les commentaires
Voir la mise à jour pour une autre approche.
la source
variable
vérité{}
évaluera à la vérité, donc cette solution est assez robuste.*ngIf="{ expanded: false } as scope"
et ensuite, si vous utilisez bootstrap, vous pouvez simplement utiliser[ngClass]="{ 'in': scope.expanded }"
et(click)="scope.expanded = !scope.expanded"
au lieu d'ajouter quoi que ce soit à vos fichiersjs
/ts
.*ngIf
truc simple au lieu d'un ngvar personnalisé): github.com/angular/angular/issues/14985Moche, mais:
Lorsqu'il est utilisé avec un tuyau asynchrone:
la source
*ngFor="let a of [(someStream$ | async).someA]
aussi. Je suppose qu'utilisé avec un<ng-container>
il sert parfaitement le travail!*ngFor
, gardez à l'esprit que tout le contenu imbriqué sera recréé si la valeur de la variable change, jusqu'à ce que vous spécifiiez unetrackBy
fonction qui renvoie le même identifiant pour toutes les valeurs.Vous pouvez déclarer des variables en code html en utilisant un
template
élément dans Angular 2 oung-template
dans Angular 4+.Les modèles ont un objet de contexte dont les propriétés peuvent être affectées à des variables à l'aide de
let
la syntaxe de liaison. Notez que vous devez spécifier une sortie pour le modèle, mais cela peut être une référence à lui-même.Vous pouvez réduire la quantité de code en utilisant la
$implicit
propriété de l'objet de contexte au lieu d'une propriété personnalisée.L'objet de contexte peut être un objet littéral ou toute autre expression de liaison. Même les tuyaux semblent fonctionner lorsqu'ils sont entourés de parenthèses.
Exemples valides de
ngTemplateOutletContext
:[ngTemplateOutletContext]="{ aVariable: 123 }"
[ngTemplateOutletContext]="{ aVariable: (3.141592 | number:'3.1-5') }"
[ngTemplateOutletContext]="{ aVariable: anotherVariable }"
utiliser aveclet-a="aVariable"
[ngTemplateOutletContext]="{ $implicit: anotherVariable }"
utiliser aveclet-a
[ngTemplateOutletContext]="ctx"
oùctx
est une propriété publiquela source
<template>
dans Angular 2. Vous pouvez utiliser soit<template>
ou l' ou<ng-template>
dans Angular 4, mais vous ne devez utiliser que<ng-template>
. Angular 5 a abandonné le support pour<template>
.t
pour?#t
est une variable de modèle qui stocke le fichierng-template
. Il est utilisé dans[ngTemplateOutlet]="t"
pour créer la référence ng-template elle-même.mise à jour 3
Le problème 2451 est résolu dans Angular 4.0.0
Voir également
mise à jour 2
Ce n'est pas pris en charge.
Il existe des variables de modèle mais il n'est pas pris en charge pour attribuer des valeurs arbitraires. Ils ne peuvent être utilisés que pour faire référence aux éléments auxquels ils sont appliqués, aux noms exportés de directives ou de composants et aux variables de portée pour les directives structurelles telles que
ngFor
,Voir aussi https://github.com/angular/angular/issues/2451
Mise à jour 1
et initialisez-le comme
ou
et utilisez la variable comme
(pas testé)
#aVariable
crée une référence auVarDirective
(exportAs: 'var'
)var="abc"
instancie leVarDirective
et transmet la valeur de chaîne"abc"
à son entrée de valeur.aVariable.var
lit la valeur affectée à l' entrée desvar
directivesvar
.la source
component.ts
fichier. Mais c'est tellement plus facile pour moi de les avoir dans la vue dans certains cas en raison d'un schéma de synchronisation que j'implémente dans mon application. Je profite des règles de référence javascript lorsque différentes variables pointent vers le même objet.There is no directive with "exportAs" set to "var"
. Quelqu'un peut-il me dire quelle erreur j'ai fait? J'ai utilisé la directive ci-dessus.declarations: [...]
of@NgModule()
. Si ce n'est pas le problème, veuillez créer une nouvelle question et fournir le code qui permet de diagnostiquer le problème.Je suggérerais ceci: https://medium.com/@AustinMatherne/angular-let-directive-a168d4248138
Cette directive vous permet d'écrire quelque chose comme:
la source
Voici une directive que j'ai écrite qui développe l'utilisation du paramètre de décorateur exportAs, et vous permet d'utiliser un dictionnaire comme variable locale.
Vous pouvez l'utiliser comme suit dans un modèle:
Bien sûr, #local peut être n'importe quel nom de variable locale valide.
la source
[key: string]: any;
à laClass
pour contourner ce problème.Si vous souhaitez obtenir la réponse d'une fonction et la définir dans une variable, vous pouvez l'utiliser comme suit dans le modèle, en utilisant
ng-container
pour éviter de modifier le modèle.Et la méthode dans le composant peut être quelque chose comme
la source
Si vous avez besoin d'une prise en charge de la saisie semi-automatique de l'intérieur dans vos modèles du service de langage angulaire :
Synchrone:
Utilisation du tube asynchrone:
la source
J'utilise angular 6x et j'ai fini par utiliser l'extrait ci-dessous. J'ai un scénario où je dois trouver un utilisateur à partir d'un objet de tâche. il contient un tableau d'utilisateurs mais je dois choisir l'utilisateur assigné.
la source
C'est beaucoup plus simple, pas besoin de rien de plus. Dans mon exemple, je déclare la variable «ouverte» puis je l'utilise.
la source
"?"
parce que j'avais le message "L'identifiant 'valeur' n'est pas défini" comme ça => "open? .Value" Mais ça marche !!J'ai aimé l'approche consistant à créer une directive pour ce faire (bon appel @yurzui).
J'ai fini par trouver un article Medium Directive "let" angulaire qui explique bien ce problème et propose une directive let personnalisée qui a fonctionné très bien pour mon cas d'utilisation avec des changements de code minimes.
Voici l'essentiel (au moment de la publication) avec mes modifications:
Mes principaux changements ont été:
appLet: T
enappLet: T | null
Je ne sais pas pourquoi l'équipe Angular n'a pas seulement fait une directive officielle ngLet, mais quoi.
Le crédit du code source original revient à @AustinMatherne
la source
Réponse courte qui aide quelqu'un
* Cependant, vous pouvez utiliser le décorateur ViewChild pour le référencer dans votre composant.
Référence variable firstNameInput à l'intérieur du composant
Après cela, vous pouvez utiliser this.nameInputRef n'importe où dans votre Component.
Travailler avec ng-template
Dans le cas de ng-template, c'est un peu différent car chaque template a son propre ensemble de variables d'entrée.
https://stackblitz.com/edit/angular-2-template-reference-variable
la source
Pour ceux qui ont décidé d'utiliser une directive structurelle en remplacement de
*ngIf
, gardez à l'esprit que le contexte de la directive n'est pas de type vérifié par défaut. Pour créer unengTemplateContextGuard
propriété de directive de type sécurisé , vous devez ajouter, voir Saisie du contexte de la directive . Par exemple:La directive peut être utilisée comme
*ngIf
, sauf qu'elle peut stocker de fausses valeurs:Le seul inconvénient par rapport à
*ngIf
est que Angular Language Service ne peut pas déterminer le type de variable, il n'y a donc pas de complétion de code dans les modèles. J'espère que cela sera corrigé bientôt.la source