formularios - tablas angular 4
¿Hay una manera de agregar una aserción/anotación de tipo a una variable de entrada de plantilla? (5)
¡Vamos a ver qué angular tiene algo similar y cómo funciona!
<p *ngFor="let number of [{v: 101},{v: 102}, {v: 103}]">{{number.v}}</p>
Podemos reescribirlo sin *
magia.
<ng-template ngFor let-number [ngForOf]="[{v: 101},{v: 102}, {v: 103}]">
<p>{{number.v}}</p>
</ng-template>
Sin observadores (ngDoCheck) puede ser el mismo que (pero ngTemplateOutlet no tiene verificación de tipo ):
<ng-template let-number #templateRef>
<p>{{number.v}}</p>
</ng-template>
<ng-container *ngTemplateOutlet="templateRef; context: {$implicit: {v: 101}}"></ng-container>
<ng-container *ngTemplateOutlet="templateRef; context: {$implicit: {v: 102}}"></ng-container>
<ng-container *ngTemplateOutlet="templateRef; context: {$implicit: {v: 103}}"></ng-container>
O podemos crearlo por nosotros mismos.
// template
<button (click)=create(templateRef)>create</button>
// TS
constructor(private _viewContainerRef: ViewContainerRef) {
}
create(templateRef: TemplateRef<{$implicit: {v: number;}}>) {
this._viewContainerRef.createEmbeddedView(templateRef, {$implicit: {v: 101}});
this._viewContainerRef.createEmbeddedView(templateRef, {$implicit: {v: 102}});
this._viewContainerRef.createEmbeddedView(templateRef, {$implicit: {v: 103}});
}
TL; DR
La magia de comprobación de plantillas de plantilla ocurre dentro de viewContainerRef.createEmbeddedView
. (por ejemplo ngFor ); Pero asume lo que acepta templateRef.
Angular se puede compilar en AOT:
<p *ngFor="let num of [{v:1}, {v:2}]">
{{num.does.not.exist.completly}}
</p>
Entonces, como entendí, deberíamos asumir qué tipos de plantillas tienen pero verificar cuándo se createEmbeddedView
instancia de la plantilla (mediante createEmbeddedView
);
Fondo
Tengo una plantilla que se parece a esto (estoy usando algún componente que usa esto como base para un elemento repetido, es la p-pickList, pero la pregunta no es específica sobre ese componente, solo como un ejemplo)
Para el fondo, digamos que tengo un tipo Foo
y mi componente tiene un foos: Foo[]
, lo estoy <p-pickList>
componente <p-pickList>
bajo el atributo [source]
y está haciendo el *ngFor
interno para ello, todo lo que tengo que hacer es proporcionar una plantilla
<ng-template let-foo pTemplate="item">
...
{{ foo.anythingGoesHereWithNoWarningAndNoAutocomplete }}
Sin embargo, la información de tipo en foo
parece estar perdida.
Soy un gran fan de la seguridad de tipos y me gusta que Intellij (o cualquier otro editor) pueda mostrarme una advertencia si dentro de la plantilla hago algo como especificar un atributo no válido de foo
Si tuviera un *ngFor
regular, *ngFor
el tipo de foo
<div *ngFor="let foo of foos">
{{ foo.autoCompleteWorksInMostIDEsAsWellAsWarningIfInvalidProp }}
Preguntas:
¿Hay alguna sintaxis que me permita insinuar el tipo de
let-foo
? (y esperamos que la mayoría de los IDEs lo reconozcan).Si no quiero confiar en IDE, ¿hay alguna forma de que el tipo de compilador ng verifique
foo
(declarado por let-foo)?
tl; dr ¿hay una sintaxis que me permita escribir y anotar la variable de entrada de la plantilla? por ejemplo, algo como esto se compone sintaxis?
let-foo="$implicit as Foo"
o let-foo-type="Foo"
?
Solución
Una idea tonta es tener una función de identidad en mi componente, por ejemplo,
identity(foo: Foo): Foo {
return foo;
}
pero haciendo
{{ identity(foo).fooProp }}
No es una gran mejora sobre
{{ (foo as Foo).fooProp }}
El problema es que no hay ningún tipo de información. <ng-template let-foo pTemplate="item">
- es solo una declaración de plantilla, aún no está enlazado a ningún tipo / contexto, solo un tipo dinámico que tiene o puede tener anythingGoesHereWithNoWarningAndNoAutocomplete
campo anythingGoesHereWithNoWarningAndNoAutocomplete
. Sin el apoyo genérico adecuado no es posible tener este tipo de seguridad de tipos.
Encontré este problema y la solución propuesta para permitir que las variables de entrada de la plantilla publiquen información de tipo para que los IDE puedan proporcionar una mejor terminación en github here . Esta característica se encuentra actualmente en desarrollo y es de esperar que salga a la venta en el futuro de Angular. Debes usar la extensión del marketplace.visualstudio.com/items?itemName=Angular.ng-template en el Código VS o Texto Sublime por ahora. Puede estar seguro del soporte de la extensión porque el equipo de Angular está trabajando en ello. Para obtener más información, consulte este readme y documentos .
Como mencionó, se puede lograr mediante el uso de la función de identidad, pero causará un gran problema de rendimiento y será un desastre mantener esta funcionalidad para diferentes tipos.
Usar Interfaces puede lograr el comportamiento que mencionas:
En el archivo ts, defina una interfaz:
export interface Dog {
name: string;
age: number;
}
en el componente define la variable:
@Component()...{
...
mrSnuggles: Dog = {
name: ''mrSnuggles'',
age: 10
};
}
y en la plantilla:
{{mrSnuggles.food}}
Se puede ver el error (intelecto idea):
VSCode debe tener esa característica lista para usar, solo se ha probado en stackblitz: https://stackblitz.com/edit/angular-type-assertion?file=src/app/app.component.html