2016-01-02 5 views
7

Можете ли вы программно инициировать обнаружение изменений углов при изменении свойства компонента в угловом2?ngOnChanges не срабатывает при изменении свойства ввода

@Component({ 
    selector: 'my-component', 
}) 
class MyComponent implements OnChanges { 
    @Input() message: string; 

    ngOnChanges(changeRecord) { 
     for (var change in changeRecord) { 
     console.log('changed: ' + change); 
     } 
    } 

    doSomething() { 
    // I want ngOnChanges to be called some time after I set the 
    // message. Currently it is only called if the host element 
    // changes the value of [message] on the element. 
    this.message = 'some important stuff'; 
    } 
} 
+3

Чтобы вручную запустить обнаружение изменений, попробуйте использовать ApplicationRef.tick(). Однако я не верю, что ngOnChanges() будет вызываться, поскольку свойство хоста не изменилось. Почему вы изменяете дочернее свойство в дочернем компоненте, являющемся входным свойством? –

+0

Код выше не является фактическим кодом, я просто использовал его, чтобы продемонстрировать проблему. Мой реальный код - это единичный тест, и я получил экземпляр компонента с помощью 'TestComponentBuilder'. Я хочу, чтобы модульный тестовый код изменял значение свойства 'message' и проверял, что событие выдается из кода в' ngOnChanges'. Но через пару часов голова царапается, я не могу понять, как это сделать. Я также пробовал модифицировать 'nativeElement' на' DebugElement', чтобы не повлиять. – ovangle

+0

Я искал такой метод, как 'ComponentFixture.modifyHostBinding (свойство: string, newValue: any)' или что-то подобное, но похоже, что ничего подобного не было, поэтому я задал более общий вопрос. – ovangle

ответ

1

Там, кажется, нет никакого способа, чтобы изменить вход связывания на this и он обнаружен во время обнаружения изменений. Однако можно было зафиксировать модульное тестирование я писал, окружив весь компонент в другом компоненте

@ng.Component({ 
    selector: 'my-host-component', 
    template: '<my-component [message]="message" (change)="change.emit($event)"></my-component>' 
    directives: [MyComponent] 
}) 
class MyHostComponent { 
    message: string; 
    change = new EventEmitter<any>(); 
} 

Я побежал тест на MyHostComponent, а не MyComponent.

Я отправил issue to angular с просьбой добавить метод к ComponentFixture, чтобы тесты, подобные этому, были легче писать.

2

У меня была такая же проблема, и это простой, но не очень элегантный обходной путь, который я использую. Перейдите в другое свойство, чтобы заставить методу запуска ngOnChanges

<div poll-stat-chart [barData]="barData" [changeTrigger]="changeTrigger"></div> 

В классе родительского компонента, каждый раз, когда вы хотите вручную огонь метод ngOnChanges на ребенка компоненте, просто изменить свойство «changeTrigger»

ParentComponent Class (poll- стат-диаграмма является дочерним компонентом)

 @Component({ 
     directives: [PollStatChartCmp], 
     template: ` 
      <div poll-stat-chart [barData]="barData" [changeTrigger]="changeTrigger"> 
      </div> 
      <button (click)="triggerChild()"></button> 
     ` 
     } 
    export class ParentComponent { 
     changeTrigger = 1; 
     barData = [{key:1, value:'1'}, {key:2, value'2'}]; 
     triggerChild() { 
      this.barData[0].value = 'changedValue'; 

      //This will force fire ngOnChanges method of PollStatChartComponent 
      this.changeTrigger ++ ;   
     } 

    } 

А потом в классе компонента ребенка, добавьте свойство [changeTrigger]

@Component({ 
     selector: '[poll-stat-chart]', 
     inputs: ['barData', 'changeTrigger'], 
     template: ` 
      <h4>This should be a BAR CHAR</h4> 
     ` 
    }) 
    export class PollStatChartCmp { 
     barData; 
     changeTrigger; 
     constructor(private elementRef: ElementRef) { 
      this.render(); 

     } 

     ngOnChanges(changes) { 
      console.log('ngOnChanges fired'); 
      this.render(); 
     } 

     render() { console.log('render fired');} 

} 
+0

Такой элегантный хак , –

2

Попытка вручную вызвать обнаружение изменений или потратил много времени на обходном пути для этого является способом overkilling, почему бы не создать функцию для обработки нужной мутации и вызвать его в обоих ngOnChanges и doSomething? что-то вроде:

@Component({ 
    selector: 'my-component', 
}) 
class MyComponent implements OnChanges { 
    @Input() message: string; 
    viewMessage: string; 

    ngOnChanges(changes: { [propertyName: string]: SimpleChange }) { 
    for (let propName in changes) { 
     if (propName === 'message') { 
     this.updateView(this.message); 
     } 
    } 
    } 

    doSomething() { 
    this.viewMessage = 'some important stuff'; 
    } 

    updateView(message: string) { 
    this.viewMessage = message; 
    } 
} 

Так viewMessage будет атрибут, который вы будете использовать и контролировать шаблон.

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