I have an rzslider that is set to default values.
HTML:
<div id="slider">
<rzslider class="with-legend"
rz-slider-model="slider.value"
rz-slider-options="slider.options">
</rzslider>
</div>
Javascript:
$scope.slider = {
this.value = 0;
this.options = {
floor: 0,
ceil: 0
}
Inside a Watch Expression, there is code that updates the slider's options:
$scope.$watch('foo', function () {
$scope.slider.value = 0;
$scope.slider.options.floor = 0;
$scope.slider.options.ceil = foo.length;
}
After the code inside the watch expression is run, I expect the slider's ceiling option to change. However, even though the values of $scope.slider
have been updated correctly, the change does not appear on the slider itself.
I have tried to re-render the slider as documented on the AngularJS Slider Github page, but it doesn't fix the issue.
$scope.refreshSlider = function() {
$timeout(function() {
$scope.$broadcast('rzSliderForceRender')
})
}
After quite some digging, we found that this was a timing issue. Note that this is only a problem in the first angular digest cycle when the rzslider is set to the default value and updated by the watch expression in the same digest cycle.
The combination of the rzslider update options code and the angular watch expression code causes the rzslider to miss the update in the first digest cycle.
This is the rzslider update options code:
this.scope.$watch('rzSliderOptions()', function(newValue, oldValue) {
if (newValue === oldValue)
return;
self.applyOptions(); // need to be called before synchronizing the values
self.syncLowValue();
if (self.range)
self.syncHighValue();
self.resetSlider();
}, true);
This is the angular watch expression code that calls the rzslider update options code:
watch.fn(value, ((last === initWatchVal) ? value : last), current);
In the first digest loop last
equals initWatchVal
, because (according to angular) there has been no change.
Determining oldValue
This means that both the newValue
and the oldValue
in the rzslider code contain the updated version of slider options. When these values are compared, the function returns before ever calling self.applyOptions();
, which would have updated the slider.
There are two possible solutions:
Update the slider options after the first digest loop has finished running. This can be done using a timeout or adding the update code to a button-click event.
Render the slider after the slider options have already been updated. We achieved this by putting the rzslider inside an ng-if
. The rzslider is created with the updated values from the start when we show the element.