2

I'm in the process of learning AngularJS for use in a specific project. In this project, there are products that can be customized by editing a list of parameters (specific to the product). I'm trying to use ngRepeat in order to render, for each parameter, an input field with a customizable spinner, and a slider.

Since I didn't find suitable plugins/directives/whatever using pure angular, I had to resort to jQueryUI Slider and Spinner plugins.

After some trial and error (and some basic google-fu) I managed to bind the spinner and the slider to the same scope variable, using directives and trying to keep on the "Angular path" as much as possible.

Here's the working fiddle: http://jsfiddle.net/b8gs60fa/4/

Then I tried implementing it using actual parameter data arranged inside an array of objects, and all hell broke loose.

Here's the broken fiddle: http://jsfiddle.net/wh3qv3rs/1/

First of all, the slider stopped working. The console shows a jQueryUI error "closestHandle is undefined" whenever I try using a slider.

Also, now the slider will be updated by using the spinner, but the model itself will not change. If a value is manually typed into the textbox, then the model is correctly updated, but the slider is not.

My guess is that the problem is being caused by this:

scope.$apply(function() {
    scope[attrs.ngModel] = (parseFloat(ui.value));
});

I'm thinking that data binding is working correctly (because typing in the textbox will change the label as well), but since ngRepeat creates a new scope for each iteration, I'm just referring to (and updating) the wrong object. Sadly, I have no idea how to fix this.

As for the "closestHandle is undefined" error, I have no clue of what's causing it to show up, and I'm secretly hoping that, by solving the binding issue, this one will automagically implode as well.

Thanks in advance.

1 Answer 1

3

Transform your directives, so they have isolated scopes, then you should not face any problems to use them in ng-repeat. Here I changed your slider:

app.directive('slider', function() {
    return {
        scope : {
            ngModel : '='
        },
        restrict: 'A',
        link: function(scope, element, attrs) {
            console.log(scope.ngModel);
            $(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.ngModel = (parseFloat(ui.value));
                    });
                }
            });
            scope.$watch(function() {return scope.ngModel; }, function() {
                $(element).slider("value", scope.ngModel);
            });
        }
    };
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! I knew I was missing something. I've also changed the spinner directive and it works perfectly. Here's an updated fiddle in case someone needs it: jsfiddle.net/wh3qv3rs/2 Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.