¿Estoy interesado en saber cuál es el requisito / caso de uso para querer cambiar el nombre de un parámetro de enlace como este ejemplo?
LDJ
31
Es solo para evitar repetir algo como tab [elemento] .val por instancia. Sé que puedo resolver el problema en el componente, pero solo estaba mirando cómo hacerlo en la plantilla (aunque no pueda terminar con esa solución).
Scipion
2
@LDJ un caso de uso de muestra: eficiencia. Use la muestra de stackblitz.com/angular/… <mat-checkbox [check] = "descendantsAllSelected (node)" [indeterminate] = "descendantsPartiallySelected (node)" (change) = "todoItemSelectionToggle (node)"> {{node. item}} </mat-checkbox> de hecho, los descedantsPartiallySelected () llama a descedantsAllSelected (). Significa que en algún momento descendientesAllSelected se llama dos veces. Si hay una variable local, esto se puede evitar.
Steven.Xi
3
<div *ngIf="{name:'john'} as user1; let user"> <i>{{user1|json}}</i> <i>{{user|json}}</i> </div>
dasfdsa
@dasfdsa, creo user1 === user, así lo haces *ngIf="{name:'john'} as user1o *ngIf="{name:'john'};let usercomo en la respuesta de yurzui .
CPHPython
Respuestas:
175
Actualizar
Podemos simplemente crear directivas como *ngIfy llamarlo*ngVar
Esto funcionará en la mayoría de los casos, pero no es una solución general ya que depende de variableestar Truthy
Keith
66
@Keith Gracias por señalar esto. Puedes echar un vistazo a mi respuesta actualizada
yurzui
3
Esta debería ser la nueva respuesta, ya que 1) es más moderna que la otra solución 2) resume las solicitudes de extracción vinculadas en la respuesta actual y ahorra mucho tiempo 3) incluye los ejemplos en línea en lugar de por enlace externo. Gracias por mostrar esto. AFAIK cualquier objeto envuelto {}se evaluará como verdadero, por lo que esta solución es bastante robusta.
kvanberendonck
44
Por ejemplo, botones expandibles: *ngIf="{ expanded: false } as scope"y luego, si está usando bootstrap, puede usar [ngClass]="{ 'in': scope.expanded }"y en (click)="scope.expanded = !scope.expanded"lugar de agregar cualquier cosa a sus archivos js/ ts.
Ese es el que se me ocurrió por instinto, también funciona *ngFor="let a of [(someStream$ | async).someA]. ¡Supongo que si se usa con un <ng-container>bien, funciona bien!
Angelos Pikoulas
2
En este caso *ngFor, tenga en cuenta que todo el contenido anidado se volverá a crear si el valor de la variable cambia, hasta que especifique una trackByfunción que devuelva la misma identificación para todos los valores.
Valeriy Katkov
76
Puede declarar variables en código html utilizando un templateelemento en Angular 2 o ng-templateen Angular 4+.
Las plantillas tienen un objeto de contexto cuyas propiedades pueden asignarse a variables mediante letla sintaxis de enlace. Tenga en cuenta que debe especificar una salida para la plantilla, pero puede ser una referencia a sí misma.
El objeto de contexto puede ser un objeto literal o cualquier otra expresión vinculante. Incluso las tuberías parecen funcionar cuando están rodeadas de paréntesis.
Para que funcione, tuve que cambiar su código de '<template ...' a '<ng-template ...'.
Humppakäräjät
2
Sí, solo puede usar <template>en Angular 2. Puede usar uno <template>o <ng-template>en Angular 4, pero solo debe usar <ng-template>. Angular 5 dejó caer el soporte para <template>.
Steven Liekens
¿Para qué sirve t?
matttm
1
@matttm #tes una variable de plantilla que almacena el ng-template. Se utiliza [ngTemplateOutlet]="t"para hacer que la plantilla ng haga referencia a sí misma.
Steven Liekens
Esto es extraño, ¡pero funciona! Angular debería hacerlo más simple, con una directiva variable incorporada. Gracias.
Hay variables de plantilla pero no es compatible para asignar valores arbitrarios. Solo se pueden usar para referirse a los elementos a los que se aplican, los nombres exportados de directivas o componentes y las variables de alcance para directivas estructurales como ngFor,
¿No sería posible crear una directiva estructural para hacerlo?
Scipion
Si necesita esto repetidamente, entonces una directiva podría hacer lo que quiera. Una directiva estructural crea su propia vista, eso probablemente no sea lo que desea.
Günter Zöchbauer
1
@ GünterZöchbauer, muy buenas cosas. Sé que probablemente sea una mejor práctica tener variables calculadas / preparadas en el component.tsarchivo. Pero es mucho más fácil para mí tenerlos a la vista en algunos casos debido a un esquema de sincronización que estoy implementando en toda mi aplicación. Aprovecho las reglas de referencia de JavaScript cuando diferentes variables apuntan al mismo objeto.
AmmarCSE
Me aparece un error como There is no directive with "exportAs" set to "var". ¿Alguien puede decirme qué error cometí? He usado la directiva anterior.
Partha Sarathi Ghosh
Quizás no agregaste la directiva declarations: [...]de @NgModule(). Si este no es el problema, cree una nueva pregunta y proporcione el código que permita diagnosticar el problema.
No pasa una compilación de 'producción' tal cual (también se muestra como errores por IDE). Agregue [key: string]: any;al Classpara evitar esto.
Charly
7
En caso de que desee obtener la respuesta de una función y establecerla en una variable, puede usarla de la siguiente manera en la plantilla, ng-containerpara evitar modificar la plantilla.
<ng-container *ngIf="methodName(parameters) as respObject">
{{respObject.name}}
</ng-container>
Y el método en el componente puede ser algo como
methodName(parameters: any): any {return{name:'Test name'};}
Estoy usando angular 6x y terminé usando el fragmento a continuación. Tengo un escenario donde tengo que encontrar usuarios de un objeto de tarea. Contiene una variedad de usuarios, pero tengo que elegir el usuario asignado.
si nombra una etiqueta, no está declarando variable
Amirreza
1
@Amirreza, para ser precisos, estoy usando ElementRef para almacenar temporalmente un valor.
Jack Rus
¡Increíble! Tuve que usar "?"porque tenía el mensaje "El identificador 'valor' no está definido" como este => "abrir? .Valor" ¡Pero está funcionando!
A. Morel
1
Me gustó el enfoque de crear una directiva para hacer esto (buena llamada @yurzui).
Terminé encontrando un artículo medio de la Directiva angular "let" que explica muy bien este problema y propone una directiva let personalizada que terminó funcionando muy bien para mi caso de uso con cambios mínimos de código.
Aquí está la esencia (en el momento de la publicación) con mis modificaciones:
Para aquellos que decidieron usar una directiva estructural como reemplazo de *ngIf, tenga en cuenta que el contexto de la directiva no está marcado de forma predeterminada. Para crear una ngTemplateContextGuardpropiedad de directiva de tipo seguro , debe agregarse, consulte Escribir el contexto de la directiva . Por ejemplo:
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 directiva se puede usar igual que *ngIf, excepto que puede almacenar valores falsos :
<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>
El único inconveniente en comparación con *ngIfes que Angular Language Service no puede determinar el tipo de variable, por lo que no hay finalización de código en las plantillas. Espero que se solucione pronto.
<div *ngIf="{name:'john'} as user1; let user"> <i>{{user1|json}}</i> <i>{{user|json}}</i> </div>
user1 === user
, así lo haces*ngIf="{name:'john'} as user1
o*ngIf="{name:'john'};let user
como en la respuesta de yurzui .Respuestas:
Actualizar
Podemos simplemente crear directivas como
*ngIf
y llamarlo*ngVar
ng-var.directive.ts
con esta
*ngVar
directiva podemos usar lo siguienteo
o
o
Ejemplo de Plunker Angular4 ngVar
Ver también
Respuesta original
V4 angular
1)
div
+ngIf
+let
2)
div
+ngIf
+as
ver
componente.ts
3) Si no quieres crear un contenedor como
div
puedes usarng-container
ver
Como @Keith mencionó en los comentarios
Ver actualización para otro enfoque.
fuente
variable
estar Truthy{}
se evaluará como verdadero, por lo que esta solución es bastante robusta.*ngIf="{ expanded: false } as scope"
y luego, si está usando bootstrap, puede usar[ngClass]="{ 'in': scope.expanded }"
y en(click)="scope.expanded = !scope.expanded"
lugar de agregar cualquier cosa a sus archivosjs
/ts
.*ngIf
ngvar en lugar de cosas personalizadas): github.com/angular/angular/issues/14985Feo, pero:
Cuando se usa con tubería asíncrona:
fuente
*ngFor="let a of [(someStream$ | async).someA]
. ¡Supongo que si se usa con un<ng-container>
bien, funciona bien!*ngFor
, tenga en cuenta que todo el contenido anidado se volverá a crear si el valor de la variable cambia, hasta que especifique unatrackBy
función que devuelva la misma identificación para todos los valores.Puede declarar variables en código html utilizando un
template
elemento en Angular 2 ong-template
en Angular 4+.Las plantillas tienen un objeto de contexto cuyas propiedades pueden asignarse a variables mediante
let
la sintaxis de enlace. Tenga en cuenta que debe especificar una salida para la plantilla, pero puede ser una referencia a sí misma.Puede reducir la cantidad de código utilizando la
$implicit
propiedad del objeto de contexto en lugar de una propiedad personalizada.El objeto de contexto puede ser un objeto literal o cualquier otra expresión vinculante. Incluso las tuberías parecen funcionar cuando están rodeadas de paréntesis.
Ejemplos válidos de
ngTemplateOutletContext
:[ngTemplateOutletContext]="{ aVariable: 123 }"
[ngTemplateOutletContext]="{ aVariable: (3.141592 | number:'3.1-5') }"
[ngTemplateOutletContext]="{ aVariable: anotherVariable }"
usar conlet-a="aVariable"
[ngTemplateOutletContext]="{ $implicit: anotherVariable }"
usar conlet-a
[ngTemplateOutletContext]="ctx"
dondectx
es una propiedad publicafuente
<template>
en Angular 2. Puede usar uno<template>
o<ng-template>
en Angular 4, pero solo debe usar<ng-template>
. Angular 5 dejó caer el soporte para<template>
.t
?#t
es una variable de plantilla que almacena elng-template
. Se utiliza[ngTemplateOutlet]="t"
para hacer que la plantilla ng haga referencia a sí misma.actualización 3
El problema 2451 se corrige en Angular 4.0.0
Ver también
actualización 2
Esto no es compatible.
Hay variables de plantilla pero no es compatible para asignar valores arbitrarios. Solo se pueden usar para referirse a los elementos a los que se aplican, los nombres exportados de directivas o componentes y las variables de alcance para directivas estructurales como
ngFor
,Ver también https://github.com/angular/angular/issues/2451
Actualización 1
e inicializarlo como
o
y usar la variable como
(no probado)
#aVariable
crea una referencia aVarDirective
(exportAs: 'var'
)var="abc"
crea una instancia deVarDirective
y pasa el valor de la cadena"abc"
a su entrada de valor.aVariable.var
lee el valor asignado a la entrada devar
directivasvar
.fuente
component.ts
archivo. Pero es mucho más fácil para mí tenerlos a la vista en algunos casos debido a un esquema de sincronización que estoy implementando en toda mi aplicación. Aprovecho las reglas de referencia de JavaScript cuando diferentes variables apuntan al mismo objeto.There is no directive with "exportAs" set to "var"
. ¿Alguien puede decirme qué error cometí? He usado la directiva anterior.declarations: [...]
de@NgModule()
. Si este no es el problema, cree una nueva pregunta y proporcione el código que permita diagnosticar el problema.Sugeriría esto: https://medium.com/@AustinMatherne/angular-let-directive-a168d4248138
Esta directiva le permite escribir algo como:
fuente
Aquí hay una directiva que escribí que amplía el uso del parámetro decorador exportAs y le permite usar un diccionario como una variable local.
Puede usarlo de la siguiente manera en una plantilla:
Por supuesto, #local puede ser cualquier nombre de variable local válido.
fuente
[key: string]: any;
alClass
para evitar esto.En caso de que desee obtener la respuesta de una función y establecerla en una variable, puede usarla de la siguiente manera en la plantilla,
ng-container
para evitar modificar la plantilla.Y el método en el componente puede ser algo como
fuente
Si necesita soporte para autocompletar desde dentro en sus plantillas del Servicio de lenguaje angular :
Sincrónico:
Usando tubería asíncrona:
fuente
Estoy usando angular 6x y terminé usando el fragmento a continuación. Tengo un escenario donde tengo que encontrar usuarios de un objeto de tarea. Contiene una variedad de usuarios, pero tengo que elegir el usuario asignado.
fuente
Es mucho más simple, no necesita nada adicional. En mi ejemplo, declaro la variable "abrir" y luego la uso.
fuente
"?"
porque tenía el mensaje "El identificador 'valor' no está definido" como este => "abrir? .Valor" ¡Pero está funcionando!Me gustó el enfoque de crear una directiva para hacer esto (buena llamada @yurzui).
Terminé encontrando un artículo medio de la Directiva angular "let" que explica muy bien este problema y propone una directiva let personalizada que terminó funcionando muy bien para mi caso de uso con cambios mínimos de código.
Aquí está la esencia (en el momento de la publicación) con mis modificaciones:
Mis principales cambios fueron:
appLet: T
aappLet: T | null
No estoy seguro de por qué el equipo de Angular no acaba de hacer una directiva ngLet oficial, sino todo lo demás.
El crédito del código fuente original va a @AustinMatherne
fuente
Respuesta corta que ayuda a alguien
* Sin embargo, puede usar el decorador ViewChild para referenciarlo dentro de su componente.
Referencia firstNameInput variable dentro de Component
Después de eso, puede usar this.nameInputRef en cualquier lugar dentro de su Componente.
Trabajando con ng-template
En el caso de ng-template, es un poco diferente porque cada plantilla tiene su propio conjunto de variables de entrada.
https://stackblitz.com/edit/angular-2-template-reference-variable
fuente
Para aquellos que decidieron usar una directiva estructural como reemplazo de
*ngIf
, tenga en cuenta que el contexto de la directiva no está marcado de forma predeterminada. Para crear unangTemplateContextGuard
propiedad de directiva de tipo seguro , debe agregarse, consulte Escribir el contexto de la directiva . Por ejemplo:La directiva se puede usar igual que
*ngIf
, excepto que puede almacenar valores falsos :El único inconveniente en comparación con
*ngIf
es que Angular Language Service no puede determinar el tipo de variable, por lo que no hay finalización de código en las plantillas. Espero que se solucione pronto.fuente