directivas - Angular 2 hace @Input en directiva requerida
directivas angular 5 (4)
En Angular 1 podríamos hacer un atributo directivo requerido. ¿Cómo hacemos eso en Angular 2 con @Input? Los doctores no lo mencionan.
P.ej.
Component({
selector: ''my-dir'',
template: ''<div></div>''
})
export class MyComponent {
@Input() a:number; // Make this a required attribute. Throw an exception if it doesnt exist
@Input() b:number;
constructor(){
}
}
Aquí está mi solución con getters / setters. En mi humilde opinión, esta es una solución mucho más elegante, ya que todo se hace en un solo lugar y esta solución no requiere la dependencia de OnInit
.
Solución # 1
Component({
selector: ''my-dir'',
template: ''<div></div>''
})
export class MyComponent {
@Input()
get a () { throw new Error(''Attribute "a" is required''); }
set a (value: number) { Object.defineProperty(this, ''a'', { value, writable: true, configurable: true }); }
}
Solución # 2 :
Se podría hacer aún más fácil con los decoradores. Por lo tanto, en su aplicación usted define un decorador como este:
function Required(target: object, propertyKey: string) {
Object.defineProperty(target, propertyKey, {
get () {
throw new Error(`Attribute ${propertyKey} is required`);
},
set (value) {
Object.defineProperty(target, propertyKey, { value, writable: true, configurable: true });
},
});
}
Y más adelante en tu clase, solo necesitas marcar tu propiedad como se requiere así:
Component({
selector: ''my-dir'',
template: ''<div></div>''
})
export class MyComponent {
@Input() @Required a: number;
}
Explicación :
Si el atributo a
está definido, el establecedor de la propiedad a
se anulará a sí mismo y se usará el valor pasado al atributo. De lo contrario, después del componente init, la primera vez que desee utilizar la propiedad a
en su clase o plantilla, se generará un error.
Nota: los getters / setters funcionan bien dentro de los componentes / servicios de Angular, etc. y es seguro usarlos así. Pero tenga cuidado al utilizar este enfoque con clases puras fuera de Angular. El problema es cómo mecanografiado convierte getters / setters - se asignan a la propiedad de prototype
de la clase. En este caso, mutamos la propiedad prototipo que será la misma para todas las instancias de clase. Significa que podemos conseguir algo como esto:
const instance1 = new ClassStub();
instance1.property = ''some value'';
const instance2 = new ClassStub();
console.log(instance2.property); // ''some value''
Para mí, tuve que hacerlo de esta manera:
ngOnInit() { if(!this.hasOwnProperty(''a'') throw new Error("Attribute ''a'' is required"); }
Para tu información, si quieres requerir las directivas @Output, prueba esto:
export class MyComponent {
@Output() myEvent = new EventEmitter(); // This a required event
ngOnInit() {
if(this.myEvent.observers.length === 0) throw new Error("Event ''myEvent'' is required");
}
}
Puedes hacerlo así:
constructor() {}
ngOnInit() {
if (!this.a) throw new Error();
}
Verifique en ngOnInit()
(las entradas aún no están establecidas cuando se ejecuta el constructor) si el atributo tiene un valor.
Component({
selector: ''my-dir'',
template: ''<div></div>''
})
export class MyComponent {
@Input() a:number; // Make this a required attribute. Throw an exception if it doesnt exist
@Input() b:number;
constructor(){
}
ngOnInit() {
if(null == a) throw new Error("Attribute ''a'' is required");
}
}
También puede verificar en ngOnChanges(changes) {...}
si los valores no se establecieron en null
. Consulte también https://angular.io/docs/ts/latest/api/core/OnChanges-interface.html