2016-02-08 2 views
3

У меня есть компонент, который отображает список «элементов», которые являются компонентами, созданными с помощью селектора. У меня есть флажок, который я хочу, при нажатии, чтобы обновить «состояние» всех дочерних компонентов.Угловые 2 Детские компоненты обнаруживают изменения в родительском

Im действительно изо всех сил пытается найти правильное решение для этого. Для получения дополнительной информации см. Plunkr.

//our root app component 
import {Component, EventEmitter} from 'angular2/core' 

class Item { 
    name: boolean; 

    constructor(name: string) { 
    this.name = name; 
    } 
} 

@Component({ 
    selector: 'my-item', 
    template: ` 
    <div> 
     <label><input type="checkbox" [(ngModel)]="state"/> {{state}}</label> 
    </div> 
    ` 
}) 
export class MyItemComponent { 
    state: boolean = false; 
} 

@Component({ 
    selector: 'my-app', 
    template: ` 
    <div style="border: 1px solid red;"> 
     <label><input type="checkbox" [(ngModel)]="state"/> {{state}}</label> 
    </div> 
    <div *ngFor="#item of items"> 
     <my-item></my-item> 
    </div> 
    `, 
    directives: [MyItemComponent] 
}) 
export class App { 
    state: boolean = true; 
    items: Item[] = []; 

    constructor() { 
    this.items.push(new Item("hello")); 
    this.items.push(new Item("test")); 
    } 
} 

ответ

6

Update

@Component({ 
    selector: 'my-item', 
    inputs: ['state']; // added 
    template: ` 
    <div> 
     <label><input type="checkbox" [(ngModel)]="state"/> {{state}}</label> 
    </div> 
    ` 
}) 
export class MyItemComponent { 
    state: boolean = false; 
} 

, а затем использовать его как

<my-item [state]="state"></my-item> 

оригинальный

изменение угла обнаружение не обнаруживает изменений в массивах.
Это должно заставить его работать:

constructor() { 
    this.items.push(new Item("hello")); 
    this.items.push(new Item("test")); 
    this.items = this.items.slice(); 
    } 

Этого путь новый массив (копия) назначенная this.items и поэтому Угловой распознает его как изменение.

В MyItem вам нужен input

@Component({ 
    selector: 'my-item', 
    inputs: ['items']; // added 
    template: ` 
    <div> 
     <label><input type="checkbox" [(ngModel)]="state"/> {{state}}</label> 
    </div> 
    ` 
}) 
export class MyItemComponent { 
    state: boolean = false; 
    items: Item[]; // added 
} 

, то вы строите связь с

<my-item [items]="items"></my-item> 

Чтобы получить код, называемый в MyItemComponent когда items изменение реализации ngOnChanges() Смотрите также https://angular.io/docs/ts/latest/api/core/OnChanges-interface.html

export class MyItemComponent { 
    state: boolean = false; 
    items: Item[]; // added 
    ngOnChanges(changes: {[propName: string]: SimpleChange}) { 
    console.log('ngOnChanges - myProp = ' + changes['items'].currentValue); 
    } 
} 
+0

Мне не нужно, чтобы обнаружить изменения в массиве. Мне просто нужны дочерние компоненты, чтобы иметь возможность обнаруживать изменения родительского состояния «логическое». – samsamm777

+0

Тогда это тот же принцип, но вам не нужен срез и 'ngOnChanges()' –

+0

ok, спасибо за ваш вклад. Теперь я рассмотрел его, используя «свойства» Компонента. – samsamm777

3

Что сказал @ Гюнтер, это совершенно верно!

То есть, я вижу некоторые ошибки в вашем plunkr:

@Component({ 
    selector: 'my-item', 
    template: ` 
    <div>Hello</div> 
    ` 
}); // <------- Remove the ; 
export class MyItemComponent { 

} 

И вы пропустили компонент в directives собственности:

@Component({ 
    selector: 'my-app', 
    template: ` 
    <div> 
     <label><input type="checkbox" [(ngModel)]="state"/> {{state}}</label> 
    </div> 
    <div *ngFor="#item of items"> 
     <my-item></my-item> 
    </div> 
    `, 
    directives: [] // <-------- Add the MyItemComponent component 
}) 
export class App { 
    (...) 
} 

Редактировать

Вы можете использовать в @ViewChildren декоратор для ссылки детей непосредственно.

@Component({ 
    selector: 'my-app', 
    template: ` 
    (...) 
    `, 
    directives: [MyItemComponent] 
}) 
export class App { 
    (...) 
    @ViewChildren(MyItemComponent) 
    children:MyItemComponent[]; 
    (...) 
} 

Затем вы можете добавить элемент управления в вашем поле, чтобы обнаружить изменения и обновить состояние дочерних компонентов соответственно:

@Component({ 
    selector: 'my-app', 
    template: ` 
    <div style="border: 1px solid red;"> 
     <label><input type="checkbox" [(ngModel)]="state" 
      [ngFormControl]="stateCtrl"/> {{state}}</label> 
    </div> 
    <div *ngFor="#item of items"> 
     <my-item></my-item> 
    </div> 
    `, 
    directives: [MyItemComponent] 
}) 
export class App { 
    (...) 
    constructor() { 
    this.items.push(new Item("hello")); 
    this.items.push(new Item("test")); 

    this.stateCtrl = new Control(); 
    this.stateCtrl.valueChanges.subscribe(
     data => { 
     this.children._results.forEach(child => { 
      child.state = data; 
     }); 
     }); 
    } 
} 

Я обновил свой plunkr с этим подходом: https://plnkr.co/edit/nAA2VxZmWy0d4lljvPpU?p=preview.

Смотрите эту ссылку для получения более подробной информации: Why is that i can't inject the child component values into parent component?

+0

Я думаю, что забыл сохранить свои окончательные изменения в Plunkr, прежде чем вставлять ссылку. Пожалуйста, ознакомьтесь с обновленной информацией. Я не уверен, что решения - это то, чего я пытаюсь достичь. Когда я отмечаю/снимаю флажок внутри красного цвета, я хочу, чтобы оба/все дети обновили свое состояние. – samsamm777

+0

О! Я разветвил и обновил ваш plunkr с помощью подхода, основанного на декораторе '@ ViewChildren' и контроле формы. Я обновил свой ответ с его описанием ... –

+0

Интересный подход, но для этого требуется, чтобы логика компонента приложения находилась в синхронизации с шаблоном дочернего компонента - то есть логика приложения должна знать, что шаблон дочернего компонента использует состояние ' 'свойство. Это очень плотная связь, поэтому довольно хрупкая. Лучше использовать свойства ввода, которые действуют как открытый API для дочернего компонента. Другим способом сокращения связи (с вашим подходом) является добавление метода к дочернему компоненту, который устанавливает внутреннее свойство 'state'. Затем компонент приложения может вызывать этот открытый API-метод, а не напрямую изменять «состояние». –

Смежные вопросы