Reputation: 279
Plunker with an example: https://plnkr.co/edit/aWUE54EUMIm8rnw3PZOO?p=preview
First button increments the value. If the value is less than 10 the button should be enabled otherwise it should disable itself. The second button resets the value to 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
);
When the value reaches 10 the first button indeed disables itself but when I reset the value to 0 it doesn't get updated even though everything is looking ok in the output:
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
This is how the value is set:
set val(v: number){
this._val = v;
console.log("Marked for check with value "+this._val);
//this.cd.markForCheck();
this.cd.detectChanges();
}
markForCheck doesn't work either so I really don't know what to do except handle the DOM myself through ElementRef (already tried it and it works), but I don't really want to do this =)
I have been trying to detect the problem and I guess the generated factory class compares the previous value of buttonClasses with the current and it works when it goes from btn btn-outline-info btn-block
to btn btn-outline-info btn-block disabled
but not the other way around.
The picture shows what happens when I reset the value with the second button and when buttonClasses first time get's called after that.
self._expr_2 is the previous value and it's btn btn-outline-info btn-block
but it should also have disabled
. Current value does not have disabled
class which is correct.
Thanks in advance for the help. I really don't know what to do here...
Upvotes: 2
Views: 1314
Reputation: 214295
With ChangeDetectionStrategy.OnPush
strategy you have to call cd.markForCheck
API method.
The most important thing:
It marks the path from our component until root to be checked for the next change detection run.
So you need to fire it on your UIButton
ChangeDetectorRefs
otherwise change detection will work only on one button after your action.
Whenever angular2 does change detection it marks view as checked after changes.
Here is how angular2 handles click event:
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);
};
Pay attention at the line:
self.markPathToRootAsCheckOnce();
It marks current button to be checked, but second button will remain with ChangeDetectorStatus.Checked
status and omitted when checking will happen.
So your solution might look like this:
1) UIButton component
constructor(public cd: ChangeDetectorRef) {}
2) App component
@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());
}
This way both buttons will be checked
See it in action Plunker
Hope this helps you!
Upvotes: 3