Call a function on change of a select option in angularjs

I have a dropdown (Select, option), and the options get populated dynamically using ng-repeat. I want to call a function within $scope on change of the option. Here is the HTML

<div class="type-style" ng-show="accountCount > 3">
     <select class="account-filter">
          <option ng-repeat="account in getCustomerName() track by $index" ng-class="(account | limitTo: 18)" ng-bind="account.split('|')[0]"></option>
     </select>
</div>

I know we can use ng-change, but ng-change needs ng-model and I don’t think ng-model is needed in my case. Can anyone help?

As you can notice in the code, I am doing and ng-repeat on option tag. So will I get that ‘account’ which I have used in ng-repeat, in the select tag? So that I can use it in ng-model?

Also, each account is a string that has 3 values separated by a ‘|’. When I call a function on ng-change, I want to pass the 2nd value with it.

For eg: Each account has Name | number | number2. Now in ng-repeat I am just showing name, as you can see I have done a split in ng-bind. So if I use ng-model in select tag, I will just get name. But I want number to be passed as parameter in the function.

Answer

There is no problem in adding a ng-model because that will help you to use its value. For example:

<select class="account-filter" ng-change="customerSelected()" ng-model="selectedCustomer">
      <option ng-repeat="account in getCustomerName() track by $index"
          ng-class="(account | limitTo: 18)"
          ng-bind="account.split('|')[0]"
          value="{{account}}"></option>
</select>

Now you can read the selected customer’s value in your controller by simply $scope.selectedCustomer.

Update

After updating the question with more description, you have two option:

Option 1 (recommended)

You can write like this (although, you can achieve much of it in the HTML itself but it is cleaner to do in the controller):

$scope.customerSelected = function() {
     var selectedCustomer = $scope.selectedCustomer;
     if (!selectedCustomer) {
          alert("Please select a customer");
          return;
     }

     var secondId = selectedCustomer.split('|')[2];
     // You can directly put your main logic here but since you want to
     // call a separate method with passing the id
     $scope.doSomethingWithCustomer(secondId);
};

$scope.doSomethingWithCustomer = function(id) {
    // Your main logic here after selecting the customer
};

and modify your HTML as I described above:

<select class="account-filter" ng-change="customerSelected()" ng-model="selectedCustomer">
      <option ng-repeat="account in getCustomerName() track by $index"
          ng-class="(account | limitTo: 18)"
          ng-bind="account.split('|')[0]"
          value="{{account}}"></option>
</select>

Option 2 (less cleaner)

$scope.doSomethingWithCustomer = function(id) {
    // Your main logic here after selecting the 2nd customer
};

and modify your HTML as:

<select class="account-filter" ng-model="selectedCustomer"
    ng-change="doSomethingWithCustomer(selectedCustomer.split('|')[2])">
      <option ng-repeat="account in getCustomerName() track by $index" ng-class="(account | limitTo: 18)" ng-bind="account.split('|')[0]" value="{{account}}"></option>
</select>

Option 3

If you want to achieve it without the ng-model and without jQuery then you can use a directive:

See a working example below.

var a = angular.module("sa", [])

a.controller("foobar", function($scope) {
  $scope.getCustomerName = function() {
    return ['Foo', 'Bar'];
  };

  $scope.customerSelected = function() {
    console.log("I'm changed");
    alert("I'm changed");
  };
});

a.directive("changeMe", function() {
  return {
    scope: {
      changeMe: '&'
    },
    link: function($scope, element, attr) {
      element.on("change", function() {
           $scope.changeMe();
      })
    }
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="sa" ng-controller="foobar">
  <select class="account-filter" change-me="customerSelected()">
    <option ng-repeat="account in getCustomerName() track by $index" ng-class="(account | limitTo: 18)" ng-bind="account.split('|')[0]"></option>
  </select>
</div>

Leave a Reply

Your email address will not be published. Required fields are marked *