Search code examples
angularjsdirectiveangular-ngmodel

ngModel reference in directive called multiple time by view


  1. I using a directive twice in the same view.
  2. In each directive I call a template with a field and a ul list.
  3. When the user writing something, I call API which returns me an array of results.
  4. This array is used for displaying a list throught ng-repeat (ul).

The problem : If a user writing something in the field which is loaded first (first directive), the ng-repeat who is called is in the second directive.

<div style="padding: 20px;">
    <p>First directive :</p>
    <span search-box ng-model="toto"></span>
    <hr>
    <p>Second directive :</p>
    <span search-box ng-model="titi"></span>
</div>

myApp.directive('searchBox', [function() {
return {
    restrict: 'A',
    scope: {
      model: '=ngModel',
    },        
    template: ''
    +'<div>'
    +       '<input type="text" ng-model="model" />'
    +       '<ul style="background-color:#e1e1e1; width: 142px; padding: 15px;" ng-show="cities.length">'
    +'          <li ng-repeat="city in cities">'
            +'                  {{city.label}}'
    +'          </li>'
    +     '</ul>'
    +'</div>',
    replace: true,
    transclude: true,
    link: function(scope, element, attrs, ngModel) {

                    scope.cities = [];

                    scope.$watch('model', function (newValue, oldValue) { if(newValue != oldValue && newValue.length > 0) search(newValue) });

                    search = function(input) {
                scope.cities = [
              {label: 'Paris'}, 
              {label: 'London'}, 
              {label: 'New York'}, 
              {label: 'Berlin'}, 
              {label: 'Lisbonne'}
            ];
        };
    }
}

http://jsfiddle.net/hNTrv/10/

Please, write something in the first field, the result box is displayed under the second field. Why the ul don't refer to its own directive ?


Solution

  • That happens because you define your search function outside of the isolated scope of the directive. To make your code work you need to define function in scope like that:

    scope.$watch('model', function (newValue, oldValue) { if(newValue != oldValue && newValue.length > 0) scope.search(newValue) });
    
                    scope.search = function(input) {
                scope.cities = [
              {label: 'Paris'}, 
              {label: 'London'}, 
              {label: 'New York'}, 
              {label: 'Berlin'}, 
              {label: 'Lisbonne'}
            ];
        };
    

    While you failing to use isolated scope in your function, it uses last scope available to caller (your function definition being called twice for your example), so function being redefined twice and second definition being called with isolated scope from second instance of directive being used in both calls.