2016-01-13 12 views
12

Ho una semplice direttiva personalizzata con un input, che sto vincolando al mio componente. Ma per qualsiasi motivo, il metodo ngOnchanges() non si attiva quando si modifica una proprietà child della proprietà di input.Modifica della proprietà figlio Angular2 non attiva aggiornamento sulla proprietà associata

my.component.ts

import {Component} from 'angular2/core'; 
import {MyDirective} from './my.directive'; 

@Component({ 
    directives: [MyDirective], 
    selector: 'my-component', 
    templateUrl: 'Template.html' 
}) 

export class MyComponent { 
    test: { one: string; } = { one: "1" } 

    constructor() { 
     this.test.one = "2"; 
    } 
    clicked() { 
     console.log("clicked"); 
     var test2: { one: string; } = { one :"3" }; 
     this.test = test2; // THIS WORKS - because I'm changing the entire object 
     this.test.one = "4"; //THIS DOES NOT WORK - ngOnChanges is NOT fired= 
    } 
} 

my.directive.ts

import {Directive, Input} from 'angular2/core'; 
import {OnChanges} from 'angular2/core'; 

@Directive({ 
    selector: '[my-directive]', 
    inputs: ['test'] 
}) 

export class MyDirective implements OnChanges { 
    test: { one: string; } = { one: "" } 

    constructor() { } 

    ngOnChanges(value) { 
     console.log(value); 
    } 
} 

template.html

<div (click)="clicked()"> Click to change </div> 
<div my-directive [(test)]="test"> 

Qualcuno può dirmi perché?

risposta

12

In realtà, è un comportamento normale e Angular2 non supporta il confronto approfondito. Si basa solo sul confronto di riferimento. Vedi questo numero: https://github.com/angular/angular/issues/6458.

Detto questo sono alcune soluzioni alternative per notificare alla direttiva che alcuni campi in un oggetto sono stati aggiornati.

  • Riferimento alla direttiva dal componente

    export class AppComponent { 
        test: { one: string; } = { one: '1' } 
        @ViewChild(MyDirective) viewChild:MyDirective; 
    
        clicked() { 
        this.test.one = '4'; 
        this.viewChild.testChanged(this.test); 
        } 
    } 
    

    In questo caso, il metodo testChanged della direttiva è chiamato in modo esplicito. Vedi questo plunkr: https://plnkr.co/edit/TvibzkWUKNxH6uGkL6mJ?p=preview.

  • Utilizzando un evento all'interno di un servizio

    Un servizio dedicato definisce testChanged evento

    export class ChangeService { 
        testChanged: EventEmitter; 
    
        constructor() { 
        this.testChanged = new EventEmitter(); 
        } 
    } 
    

    Il componente utilizza un servizio per attivare l'evento testChanged:

    export class AppComponent { 
        constructor(service:ChangeService) { 
        this.service = service; 
        } 
    
        clicked() { 
        this.test.one = '4'; 
        this.service.testChanged.emit(this.test); 
        } 
    } 
    

    La direttiva si iscrive a questo evento testChanged in Per essere avvisato

    export class MyDirective implements OnChanges,OnInit { 
        @Input() 
        test: { one: string; } = { one: "" } 
    
        constructor(service:ChangeService) { 
        service.testChanged.subscribe(data => { 
         console.log('test object updated!'); 
        }); 
        } 
    } 
    

Spero che ti aiuta, Thierry

+0

Nessuno di questi sembra funzionare per me. Ho provato a impostare esplicitamente l'emettitore testChange su @Output() e ho provato ad essere type-specifc con il valore , ma semplicemente non attiva ngOnchanges nella direttiva. – Dynde

+0

Quale versione di Angular2 usi perché l'ho fatta funzionare con la versione beta0? –

+0

Sono anche su beta.0. La dichiarazione di testChange non è valida neanche per me (devo assegnare o rinunciare alla dichiarazione del tipo e andare direttamente a: testChange = new EventEmitter();) Devo iscrivermi in qualche modo speciale nella mia direttiva per registrarlo l'eventEmitter? – Dynde

Problemi correlati