Estoy haciendo un componente personalizado para el menú desplegable. Tengo un objeto de configuración que estoy inicializando en ngOnInit() , y estoy combinando las configuraciones predeterminadas y las configuraciones proporcionadas por el usuario como @Input() , pero en tiempo de ejecución desde el componente principal, si estoy haciendo algún cambio en mi configuración object, no se actualiza en el método ngOnChanges() de mi hijo.
Intenté esto:
componente secundario
@Input() config: MyConfig; @Input() disabled: boolean ngOnChanges() { console.log('config', this.config); // this is not console.log('disabled', this.disabled); // this is detecting }componente padre html
<button (click)="changeConfig()">Change Config</button> <app-child [config]="customConfig" [disabled]="newDisabled"></app-child>componente padre ts
newDisabled = false; customConfig = { value: 'code', label: 'name', floatLabel: 'Select' }; changeConfig() { this.customConfig.value = 'name'; this.newDisabled = true; }para la variable disbale está funcionando, pero para la configuración no, ¿estoy haciendo algo mal? por favor ayuda
Su problema es que ngOnInit está configurando la variable de config en un nuevo objeto. Dado que @Input() se llama una vez, esto rompe su referencia al objeto original y no se detectarán los cambios.
Puede arreglar esto usando un setter y getter. He agregado un bombardeo de pila para demostrar esto a continuación.
componente padre
import { ChangeDetectorRef, Component, VERSION } from '@angular/core'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: ['./app.component.css'], }) export class AppComponent { newDisabled = false; customConfig = { value: 'code', label: 'name', floatLabel: 'Select', }; changeConfig1() { this.customConfig.value = 'name1'; this.newDisabled = true; console.log('Change Config 1'); } changeConfig2() { this.customConfig.value = 'name2'; this.newDisabled = true; console.log('Change Config 2'); } }componente hijo
import { Component, Input } from '@angular/core'; class MyConfig {} @Component({ selector: 'hello', template: `<h1> config: {{config | json}}</h1><h1> disabled: {{disabled}}</h1>`, styles: [], }) export class HelloComponent { private _defaultConfig = { key: 'default', }; @Input() disabled: boolean; private _config: MyConfig; @Input() config: MyConfig; set () { if (!this.config) { this.config = new MyConfig(); // it is a class } else { this._config = { ...this.config, ...this._defaultConfig, }; } } get () { return this._config; } ngOnChanges() { console.log('config', this.config); console.log('config', this._config); console.log('disabled', this.disabled); } }Los objetos de entrada se comparan por referencia, por lo que si desea reflejar los cambios en su componente secundario y desencadenar ngOnChanges , haga lo siguiente:
changeConfig() { this.customConfig = {...this.customConfig, value: 'name'};; this.newDisabled = true; } Y también mueva su código a continuación de ngOnInit a ngOnChanges , lo más probable es que en el momento de la inicialización, los cambios de entrada no estén disponibles.
if (!this.config) { this.config = new MyConfig(); // it is a class } else { this.config = { ...this._defaultConfig, ...this.config }; }El problema es que la detección de cambios solo se activa si se cambia el objeto customConfig . En su ejemplo, solo se actualiza la propiedad de value . Lo que puede hacer es lo siguiente en parent.component.ts :
changeConfig() { this.customConfig = Object.assign(this.customConfig, { value: 'name'}); this.newDisabled = true; } Esto creará un nuevo objeto de configuración que contiene la propiedad de value actualizada y todas las demás propiedades antiguas de la customConfig anterior.