Reputation: 125
I'm trying to build an Angular directive that creates a keyboard-accessible slider widget. I found several Angular sliders on Github, but none of them are keyboard-accessible. So, I'm trying to convert the jQuery UI slider to an Angular directive.
Here is how I'd build the widget without Angular.
HTML:
<div id="slider"></slider>
<input type="text" id="amount"/>
Javascript:
$("#slider").slider({
min: 1,
max: 10,
slide: function(event, ui) {
$("#amount").val(ui.value);
}
});
And this is how I'd like the Angular directive to work:
<slider min="1" max="10" ng-model="sliderValue"/>
<input type="text" ng-model="sliderValue"/>
As an example, here is a jsFiddle that shows how someone converted a jQuery UI date widget to an Angular directive.
http://jsfiddle.net/xB6c2/121/
I'd like to do something similar to this for the slider widget. Thanks!
Upvotes: 2
Views: 8080
Reputation: 833
A small improvement over the Rodney's solution:
app.directive('slider', function() {
return {
restrict: 'AE',
link: function(scope, element, attrs) {
element.slider({
value: scope[attrs.ngModel],
min: parseInt(attrs.min),
max: parseInt(attrs.max),
step: parseFloat(attrs.step),
slide: function(event, ui) {
scope.$apply(function() {
scope[attrs.ngModel] = ui.value;
});
}
});
scope.$watch(attrs.ngModel, function(newVal, oldVal){
element.slider({value: newVal});
});
}
};
});
It allows to detect and update the slider position if the model changes.
If your model contains dots (for instance, ngmodel = "Configuration.Size"
), scope[attrs.ngModel]
no longer works. A workaround is to use _.get
and _.set
from lodash
library instead.
Upvotes: 1
Reputation: 125
Here is a solution that works. Thank you to Duc Hong - his answer was instrumental in helping me to figure this out. Please let me know if there is a better way to do this.
app.directive('slider', function() {
return {
restrict: 'AE',
link: function(scope, element, attrs) {
element.slider({
value: scope[attrs.ngModel],
min: parseInt(attrs.min),
max: parseInt(attrs.max),
step: parseFloat(attrs.step),
slide: function(event, ui) {
scope.$apply(function() {
scope[attrs.ngModel] = ui.value;
});
}
});
}
};
});
Upvotes: 6
Reputation: 1179
you can write up a directive for your UI slider, it works something like this:
<input type="text" ng-model="setMin" />
<input type="text" ng-model="setMax" />
<slider min="setMin" max="setMax"></slider>
and your directive would be something like this:
app.directive("slider", function() {
return {
restrict: "AE",
scope:{
min:"=",
max:"="
},
link: function(scope, ele, attrs) {
ele.slider({
min: scope.min,
max: scope.max,
range: "min",
value: "5",
slide: function(event, ui) {
scope.$apply(function() {
//update on the view using ui.value;
//scope.number = = ui.value;
});
}
});
// You can watch the value min,max and then reapply your UI slider
scope.$watch('setMin', function(newValue, oldValue) {
if (newValue !== null && newValue !== undefined) {
// re-apply UI slider
}
}, true);
scope.$watch('setMax', function(newValue, oldValue) {
if (newValue !== null && newValue !== undefined) {
// re-apply UI slider
}
}, true);
}
}
});
Hopefully you get the idea, cheers
Upvotes: 1