2016-10-18 25 views
1

Plunker用一个例子: https://plnkr.co/edit/aWUE54EUMIm8rnw3PZOO?p=preview角2子组件未检测的变化正确地

第一个按钮递增值。如果该值小于10,则该按钮应该被启用,否则应该禁用它自己。 第二个按钮重置价值为0。

this.button1 = new ButtonAction(
    "info", 
    "check", 
    "right", 
    "Click me!", 
    "medium", 
    true, 
    true, 
    new Command(
    () => this.val += 1, 
    () => { 
     return this.val < 10; 
    } 
), 
    false 
); 

this.button2 = new ButtonAction(
    "info", 
    "check", 
    "right", 
    "Reset first button!", 
    "medium", 
    true, 
    true, 
    new Command(
    () => this.val = 0, 
    null 
), 
    false 
); 

当值达到10的第一个按钮确实禁用本身,而是当我的值重置为0它不会得到更新,即使一切都看在确定输出:

Marked for check with value 7 
btnClass: btn btn-outline-info btn-block 
isDisabled: false 
Marked for check with value 8 
btnClass: btn btn-outline-info btn-block 
isDisabled: false 
Marked for check with value 9 
btnClass: btn btn-outline-info btn-block 
isDisabled: false 
Marked for check with value 10 
btnClass: btn btn-outline-info btn-block disabled 
isDisabled: true 
Marked for check with value 0 
btnClass: btn btn-outline-info btn-block 
isDisabled: false 

这是值的设置:

set val(v: number){ 
    this._val = v; 
    console.log("Marked for check with value "+this._val); 
    //this.cd.markForCheck(); 
    this.cd.detectChanges(); 
} 

markForCheck无法正常工作或,所以我真的不知道,除了手柄次做什么e DOM自己通过ElementRef(已经尝试过它,它工作),但我真的不想这样做=)

我一直在尝试检测问题,我猜生成的工厂类比较以前的值buttonClasses与当前和它的作品时,从btn btn-outline-info btn-blockbtn btn-outline-info btn-block disabled但不是相反。

图片显示了当我用第二个按钮重置值并在第一次调用buttonClasses之后调用该值时发生的情况。 Debugging after reset button click

self._expr_2是以前的值,它是btn btn-outline-info btn-block但它也应该有disabled。当前值没有disabled这个类是正确的。

在此先感谢您的帮助。我真的不知道在这里做什么...

回答

2

随着ChangeDetectionStrategy.OnPush策略,你必须调用cd.markForCheck API方法。

最重要的一点:

,直到为 未来变化检测运行进行检查根它标志着我们的组件的路径。

所以,你需要启动它在你的UIButtonChangeDetectorRefs以其他方式改变检测你的动作之后将只在一个按钮。

每当angular2确实会改变检测,它会在更改后将视图标记为已检查。 enter image description here

这里是angular2程序如何处理点击事件:

UIButton.ngfactory。JS在该行

_View_UIButton0.prototype._handle_click_1_0 = function($event) { 
    var self = this; 
    self.markPathToRootAsCheckOnce(); 
    self.debug(1,3,14); 
    var pd_0 = (self.context.clicked() !== false); 
    return (true && pd_0); 
}; 

关注:

self.markPathToRootAsCheckOnce(); 

这标志着当前按钮进行检查,但第二个按钮将继续留在ChangeDetectorStatus.Checked状态和检查时会发生省略。

所以您的解决方案可能是这样的:

1)的UIButton组件

constructor(public cd: ChangeDetectorRef) {} 

2)应用程序组件

@ViewChildren(UIButton) buttons: QueryList<UIButton>; 

set val(v: number){ 
    this._val = v; 
    console.log("Marked for check!"); 
    this.buttons.toArray().forEach(btn => btn.cd.markForCheck()); 
} 

这样两个按钮将被选中

见它在行动Plunker

希望这可以帮助你!

+1

非常感谢。是的,我错过了从目前的观点来看根源的那部分。我认为这是另一种方式=)我已经开了我的头两天了=) – BizzyDizzy