0

I am working on a select directive that knows its repository and loads its data. this directive has a very simple template.

<select></select>

I have a compile function that adds a ng-options directive to our select. since the rendered element on the from is a select I expect that putting a ng-change directive on our element will call the related change function but it is called only once.Here's a code snippet that I made to share the code.

Here is also a plunker version of same code :https://plnkr.co/edit/D8lErJWKZyrAeI6BZ7iJ

// Code goes here

var app = angular.module("myShoppingList", []); 
app.controller("myCtrl",['$scope','productsRepository', function($scope,productsRepository) {
    $scope.products =productsRepository.getAll();
    $scope.selectdProduct={};
    $scope.onSelectedProductChanged=function(item){
      alert(item);
    }
}]);

app.service("productsRepository",[function(){
  return {
    getAll:function(){return [
      {
        id:1,title:'Milk'
      },
      {
        id:2,title:'Bread'
      },
      {
        id:3,title:'Cheese'
      }
      ]}
  }
}]);

app.directive("productsComboBox",['$compile','productsRepository',function($compile,productsRepository){
  return {
    restrict:'E',
    replace:true,
    template:'<select></select>',
    scope:{
      ngModel:'='
    },
    require:'ngModel',
    compile:function(elm,atts){
      elm.attr('ng-options','item.id as item.title for item in items' );
      var fn=$compile(elm);
      return function(scope,elm,atts){
        
          fn(scope);
          scope.items=productsRepository.getAll();
          console.log(scope.items);
      }
    }
  }
}])
<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@*" data-semver="4.0.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.10/angular.min.js"></script>
    <script data-require="angular.js@*" data-semver="4.0.0" src="script.ts"></script>
    <script data-require="angular.js@*" data-semver="4.0.0" src="system.config.js"></script>
    <script data-require="angular.js@*" data-semver="4.0.0" src="tsconfig.json"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app='myShoppingList' ng-controller='myCtrl'>
    <ul>
      <li ng-repeat='product in products'>{{product.title}}</li>
    </ul>
    <products-combo-box ng-model='selectdProduct' ng-change='onSelectedProductChanged(selectdProduct)'></products-combo-box>
  </body>

</html>

I have seen other question about the same problem but there's a difference between my problem and those questions. We don't have any root element in our template and thus ng=change is placed in our select and we can not define a ng-model for our select in our directive so that we can call the ng-change of the parent.

Beatles1692
  • 5,214
  • 34
  • 65
  • can't you do it through directive controller? You are losing the model with isolated scope, etc. It might be better to use `bindToController` and pass a reference to a function through an attribute – Aleksey Solovey Nov 13 '18 at 11:11
  • can you please explain it more in an answer. – Beatles1692 Nov 13 '18 at 11:27
  • The `ng-change` directive only works when there is an `ng-model` directive on the same element. – georgeawg Nov 13 '18 at 12:11
  • @georgeawg what do mean by same element ? cause we have a ng-model on our combo box element and when it is replaced it will be copied to our select tag. – Beatles1692 Nov 13 '18 at 12:34
  • Using `replace: true` is probably not a good idea. See [Why is `replace` property deprecated in AngularJS directives?](https://stackoverflow.com/questions/24194972/why-is-replace-property-deprecated-in-angularjs-directives/35545445#35545445). – georgeawg Nov 13 '18 at 15:28

1 Answers1

0

Try using $scope.$watch instead of ng-change, it will be easier to manage the value:

$scope.$watch('selectdProduct', function (item) {
    alert(item);
});
john doe
  • 161
  • 1
  • 1
  • 15
  • the problem is I am writing the directive for a legacy system that uses ng-change and other directives such as ng-click .I can not tell our developers to change them . we want only to replace – Beatles1692 Nov 13 '18 at 11:02
  • Using $scope.$watch might be easier but it will be far more heavy for the application. – ThibaudL Nov 13 '18 at 13:03