Tim
Tim

Reputation: 1433

bind attribute to object property in isolated scope

I have a directive (using an isolated scope) that makes use of another directive which changes a flag which I therefore had to put into a container object. Now, I also want to be able to set that flag from the outside. Let me "draw" this for you:

outerScope (outerFlag1 = true, outerFlag2 = true)
    directiveScope (container.flag1 = false, container.flag2 = false)
        subdirectiveScope (container.flag1 = false)
        subdirectiveScope (container.flag2 = false)

The flag variables in directiveScope and subdirectiveScope are always the same, because container is prototypically inherited. Now I want to be able to set it from the outside, to synchronize outerFlagX with container.flagX.

With the isolated scope definition I can map a property like so:

scope: {
        outerFlag1: '=flag1'
        outerFlag2: '=flag2'
       }

However, what I would need but is not allowed is

scope: {
        outerFlag1: '=container.flag1'
        outerFlag2: '=container.flag2'
       }

How can I get this done?

I added a plunker based on the one that Mikko provided (thanks a lot): http://plnkr.co/edit/hT6Zip

Upvotes: 0

Views: 669

Answers (2)

Tim
Tim

Reputation: 1433

The answer to my problem has two parts which are not entirely obvious from my question, so apologies for that.

  1. Simply don't use the container object. (see the plunkr in my question)

  2. While this worked in the plunker, it still didn't work in my code. So I stripped it down until it worked. The second problem was, that I used the sub-directives together with an ng-if. See a modified plunker where one of the usages features an ng-if like so:

    <sub-directive ng-if="condition" flag="flag2"> </subdirective>

Unfortunately (in this case), ng-if creates a child scope so that if the flag is modified in the sub-directive, it sets an own property in that child scope. As usual, this is not available in the parent scope (prototypical inheritance). Click on the parent checkbox first, it works as expected, clicking the sub-checkbox will break it.

So the solution is, to use ng-show instead, which does not create another scope.

Upvotes: 0

Mikko Viitala
Mikko Viitala

Reputation: 8404

It would have been great to see a real-life use case, in form of a plunker/fiddle. Your problem might go away just by not defining isolated scope in your subdirective.

Given you have following controller and two directives

// controller
app.controller('MainCtrl', function ($scope) {
  $scope.model = null;
});

// top level directive
app.directive('oneDirective', function () {
  return {
    restrict: 'E',
    scope: {
      flag: '='
    },
    template: '<label for="one">One directive</label><br>' +
              '<input type="text" name="one" ng-model="flag">' +
              '<br>' + 
              '<other-directive></other-directive>'
  }; 
});

// nested directive
app.directive('otherDirective', function () {
  return {
    restrict: 'E',
    template: '<label for="other">Other directive</label><br>' +
              '<input type="text" name="other" ng-model="flag">'
  };
});

And related HTML template

<body ng-controller="MainCtrl">
  <h4>Directive scopes</h4>
  <div>
    <label for="number">Parent scope</label><br>
    <input type="text" ng-model="model" placeholder="enter something..." />
    <hr>
  </div>
  <div>
    <one-directive flag="model"></one-directive>
  </div>
</body>

That would give you something liek

imgur

Related plunker here http://plnkr.co/edit/7XhG8e

Upvotes: 1

Related Questions