4

Why can't I have a binding in a nested object in my scope object like this:

app.directive('myDirective', function() {
    return {
        scope: {
            dropdown: {
                option: '=selectedOption' //not working
            } 
        }
    }
})

I am getting an error:

a.match is not a function

Here's a working plunker.

8
  • What do you want to achieve? Commented Jan 20, 2016 at 12:53
  • I want a variable in my directive which is a property of an object and is binded to a variable in the controller. Commented Jan 20, 2016 at 12:54
  • So have you tried like this: scope: { "dropdown.option": "=selectedOption" }? Commented Jan 20, 2016 at 12:56
  • No, that looks weird, but let me try. Commented Jan 20, 2016 at 12:56
  • 1
    can you just fiddle it out. Commented Jan 20, 2016 at 13:02

2 Answers 2

1

The answer to "why" is "because that isn't how it works".

The AngularJS source code that parses the scope for a directive is here: https://github.com/angular/angular.js/blob/master/src/ng/compile.js#L829

  function parseIsolateBindings(scope, directiveName, isController) {
    var LOCAL_REGEXP = /^\s*([@&]|=(\*?))(\??)\s*(\w*)\s*$/;

    var bindings = {};

    forEach(scope, function(definition, scopeName) {
      var match = definition.match(LOCAL_REGEXP);

      if (!match) {
        throw $compileMinErr('iscp',
            "Invalid {3} for directive '{0}'." +
            " Definition: {... {1}: '{2}' ...}",
            directiveName, scopeName, definition,
            (isController ? "controller bindings definition" :
            "isolate scope definition"));
      }

      bindings[scopeName] = {
        mode: match[1][0],
        collection: match[2] === '*',
        optional: match[3] === '?',
        attrName: match[4] || scopeName
      };
    });

    return bindings;
  }

As you can see, it does a single pass through the scope object properties and does not recursively descend into object properties.

Sign up to request clarification or add additional context in comments.

2 Comments

Got it, so it isn't possible. Can this be called as a bug? Because it is an accepted good practice to not have direct bindings to scope and this limits us to having direct bindings to scope in directives?
@TarunDugar Seems like a reasonable request to me. You can submit issues on GitHub.
0

Not sure if this will work or not:

scope: {
    "dropdown.option": "=selectedOption"
}

But, as a workaround, you can write like this:

app.directive('myDirective', function() {
    return {
        scope: {
            dropdownOption: "=selectedOption"
        },
        controller: ["$scope", function($scope) {
            $scope.dropdown = $scope.dropdown || {};

            $scope.$watch('dropdownOption', function(newValue) {
                $scope.dropdown.option = newValue;
            });


            $scope.$watch('dropdown.option', function(newValue) {
                $scope.dropdownOption = newValue;
            });
        }]
    }
})

4 Comments

First one does not work. Second one is a workaround agreed but the question is why cant we have nested objects as mentioned.
Oh! right Tarun. Not sure about the reason but probably, Angular itself doesn't supports it. Have you seen such an example out there?
No, I haven't but its a well known good practice of avoiding direct bindings with scope properties. Otherwise I can have issues like these: stackoverflow.com/questions/19310129/…. And I am also just plain curious as to why this isn't support(if it isn't). :)
Yeah, that's true. I'll delete my answer then.

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.