Reputation: 1675
I'm using AngularJS, AngularUI's jQuery passthrough uiJq and jQuery's noUiSlider plugin, but the question is really about accessing a method. The html portion correctly renders a slider, and I need to 2-way bind to the slider's output value. I tried the below javascript code and variation of them in controller unsuccessfully.
Seems like uiJq doesn't work with all jQuery plugins. I'm wondering if noUiSlider is one that doesn't work and I need to write a custom directive. Also not sure if I need to deal with Deferred Execution or need uiRefresh
to manually $watch
things.
HTML
<div class="noUiSlider" id="abc" ui-jq="noUiSlider"
ui-options="{range: [0, 100], start: 50, handles: 1}"></div>
JS
app.controller('MainCtrl', function ($scope) {
$scope.selectionValue = $('#abc').noUiSlider().val();
// error, seems to override whatever is in html
$scope.selectionValue = $('#abc').val();
// no error but no value is returned
});
Thanks!
Upvotes: 0
Views: 1876
Reputation: 564
Here is a quick dirty directive that wraps JQuery UI Slider. Just set ngModel as you always would for bi-directional binding, and add min max orientation and animation attributes to your directive tag.
Sample Usage:
<div si-slider ng-model="TargetModel.SomeIntProperty" min="100" max="2000" orientation="horizontal" animate="true"></div>
And the code:
var directives = angular.module('si.directives', []);
directives.directive('siSlider', function ($rootScope) {
var directiveDefinitionObject = {
restrict: 'EA',
transclude: 'false',
template: '<div class="slider"></div>',
replace: true,
scope: { Model:"=ngModel"},
link: function (scope, element, attrs) {
var change = function () {
scope.Model = (element).slider("value");
if (!$rootScope.$$phase) {
scope.$apply();
}
};
element.slider({
value: scope.Model,
animate: attrs.animate,
orientation: attrs.orientation,
min: parseInt(attrs.min, 10),
max: parseInt(attrs.max, 10),
slide: change,
change: change
});
scope.$watch('Model', function (value) {
element.slider("value", value);
});
}
};
return directiveDefinitionObject;
});
Upvotes: 0
Reputation: 4616
Okay so you're running into a lot of assorted issues all at once and it's hard to figure out where to start. FIRST, read this: https://github.com/angular/angular.js/wiki/Understanding-Directives
Second, DON'T use jQuery in your controller. The controller fires ONCE, and it fires BEFORE the template has 'rendered'. This means that you are retrieving DOM values before they intialized (or even exist) and you're getting an error because .noUiSlider()
was never run on the DOM element.
You have to think ASYNCHRONOUSLY when it comes to AngularJS. Templates are constantly changing and updating and refreshing and you must code with this expectation in mind.
Anyway, long story short, you're better off using the slide callback function to update the model, although this is a bit hackish and if you don't mind getting your nose wet, you can try making a new directive altogether that requires: 'ngModel'
ui-options="{range, [0,100], start: 50, handles: 1, slide: slideCallback }"
...
$scope.slideCallback = function() {
$scope.myModel = $(this).val();
// this tells angular to refresh since an async event occurred outside of angular
$scope.$apply();
};
Upvotes: 3