0

I ran into a problem with AngularJS concerning directives and ng-model.

Assume the following example:

Within my HTML file:

<div ng-controller="MyCtrl">
  <div ng-repeat="item in data">
    <directive-item data="item"/>
  </div>
  <div>
    <span>This is some input: {{ myinput }} </span>
  </div>
</div>
...

My app.js looks like this (stripped for readability):

app.controller('MyCtrl', ['$scope', function($scope) {
    $scope.data = [
      { value: 'something' }
    ];
}]);

app.directive('directiveItem', function($compile) {
  var template = '<div>'
                + '<label for="myinput">{{ data.value }}</label>'
                + '<input type="text" ng-model="myinput" />'
               + '</div>';

  var linker = function(scope, element, attrs) {
    element.html(template).show();
    $compile(element.contents())(scope);
  };

  return {
    restrict: 'E',
    link: linker,
    scope: {
      data: '='
    }
  };
});

Maybe you can see my problem. Everything works fine, except the display of {{ myinput }} outside of my directive. It works perfect, if I display it within the injected template, but not outside of it. I did a LOT of google-research, but didn't find anything to help me out.

To clear some things out in front: $scope.data contains multiple objects with different data sets in my real application. So please look at this only as a quick example. Also I do inject some more templates from my directive depending on a given $scope.data.object.type. The given code is only a rough example of what I have. As mentioned, everything else works without flaws.

Anyone here got an idea?

Regards!

€dit: @Zeeshan did come up with a good way. Not yet 100% what I am looking for, but it pushes my thinking in another direction. If anyone has the perfect solution, I am free for ideas! Thanks!

2
  • I tried to fiddle around a bit, but couldn't get it to work. Maybe this answer is helpful: stackoverflow.com/questions/15597228/… Commented Mar 10, 2015 at 12:49
  • @Rias I found that Q before and unfortunately that didn't help me, that's why I started my own Q. Thanks for your effort. Commented Mar 11, 2015 at 6:59

2 Answers 2

3

Angular Best Practice: Use the scope option to create isolate scopes when making components that you want to reuse throughout your app. I have tried a few cases to build understanding, with object (reference | alias behavior), with plain string. Following snippet simulates:

(function(angular) {
  'use strict';
angular.module('myApp', [])
  .controller('MyCtrl', ['$scope', function($scope) {
    $scope.data = [{ value: 'something' }];
    $scope.bar = {value:'barInitValueAsObject'};
    $scope.tar = 'tarInitValueAsNonObject';
}])
.directive('oneItem', function($compile) {
  return {
        restrict: 'E',
        scope: {
          foo: '=',
          bar:'=',
          tar:'=',
          },
        template: '<div><label for="bar">{{ foo }} : </label> <input type="text" ng-model="bar.value" /></div>'  
        + '<div><label for="bar">{{ foo }}</label> : <input type="text" ng-model="tar" /></div>'
  }
})
  
})(window.angular);
<!doctype html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Example - example-example15-production</title>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.5/angular.min.js"></script>
  <script src="script.js"></script>
</head>

<body ng-app="myApp">      
  <div ng-controller="MyCtrl">        
    <div ng-repeat="item in data">          
      <one-item foo="item.value" bar="bar" tar="tar"></one-item>
    </div>
    <div>
      <br><br>
      <span>This is bar @ Parent : {{ bar.value }} </span>
      <br><br>
      <span>This is tar @ Parent : {{ tar }} </span>
    </div>
  </div>
</body>

</html>

Plnkr here

Happy Helping!

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

2 Comments

Thank you for your answer! It's not yet 100% what I need, but you did push my brain in another direction ;-) I will continue to work this out and keep this Q updated! Again, thank you for your solution.
Can't yet give you a real up, because my reputation is too low (15 required on SO). Will do so as soon as I am able to. Thank you for trying to help me out.
0

You can use another two-way binding in the directive's isolate scope. You already are passing in the data variable, so just add another variable to the scope that will bind with your myInput. Since this is a two-way binding, updating the value in one way will update the value elsewhere too. You'll probably just want to let the directive (and its HTML input) handle the input.

...  
return {
    restrict: 'E',
    link: linker,
    scope: {
      data: '=',
      myInput: '='
}

Finally, your scopes are not lining up properly because of your ng-repeat. It's not clear whether you want your display within the ng-repeat or not, so I just put the display also within the ng-repeat. In your controller's HTML:

  <div ng-repeat="item in data">
    <directive-item data="item" my-input="myInput"></directive-item>
    <span>This is some input: {{ myinput }} </span>
  </div>
  <div>

  </div>

Check out this plunker.

4 Comments

Thanks for your idea, but unfortunately this does not work. I get an error after implementing your suggestion: [$compile:nonassign] Expression undefined...
Thanks again. This does work, but unfortunately that is not what I need. I really do need my <span>This is some input: {{ myInput }}</span> outside my ng-repeat. My actual application is very huge and the directive handles a ton of inputs. I need to display some of those inputs within an extra div.
@Carnivorus Ok. The only way I can think of to do that is to bind the myInput to an element of an array in your controller (or potentially to a property of the data object). Then pull the proper element to the display (not sure how you will decide which input is correct). Best of luck.
I hope there is another way, else I have to start thinking about some kind of work-around like you are proposing. Thank you anyway.

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.