Search code examples
angularjsangularjs-componentsangularjs-ng-change

Angular 1.5 ng-change on select element in component triggering previous response


I'm just starting to play with components in Angular 1.5.x and have created one for a select box on a form - I pass in the field, list and label to the component and it creates the form 'part' consisting of the label and select box with the correct options - so far, so good.

Now I want to implement an ng-change on the select so I am passing in the function I want to use for this. The problem I have is that the function is triggering with the old value for the select not the new value. I can see that the function is triggering prior to the actual change. If I put the change function within the component change event it registers correctly, but not using a passed in function.

I have created a cut-down fiddle at https://jsfiddle.net/7gd3m2k0/

<div ng-app="demoApp">
  <div ng-controller="RoleController as ctrl">
    <nac-select       
      field="ctrl.MemberRole.record.member" 
      list="ctrl.Lists.Member" 
      label="Member" 
      on-change="ctrl.MemberRole.changeMember();"></nac-select>
    <div ng-bind="ctrl.MemberRole.record.member.name"></div>
  </div>
</div>

angular.module('demoApp', [])
.component('nacSelect', nacSelect)
.controller('RoleController', roleController)

var nacSelect = {
bindings: {
            field: '=',
            list: '<',
            label: '@label',
            onChange: '&'
        },
        controller: function () {
            var ctrl = this;
            ctrl.change = function () {                    
                alert(ctrl.field.name); //gives new selection
                ctrl.onChange(); //gives previous selection
            }
        },
    template: `

    <label>{{$ctrl.label}}</label>
    <select ng-model="$ctrl.field" ng-options="r as r.name for r in $ctrl.list" ng-change="$ctrl.change();">
      <option value="">(Please Select)</option>
    </select>
`
};

var roleController = function(){
var ctrl = this;

  ctrl.Lists = {
Member: [
  {id: 1, name: 'Fred Smith'},
  {id: 2, name: 'Jenny Jones'},
  {id: 3, name: 'Jane Doe'}
]
  };

ctrl.MemberRole = {
record: {
    member: null
},
    changeMember: function(){
    alert(ctrl.MemberRole.record.member.name);    
    }  
  };
};

I guess I am missing something simple, but I can't figure it out. Thank you for your assistance


Solution

  • You need to pass in variable that you want to alert in the first controller, check this:

    https://jsfiddle.net/pegla/7gd3m2k0/1/

    so your function would look like this:

    changeMember: function(name){
            alert(name);
        }
    

    when you're using nac-select

     <nac-select field="ctrl.MemberRole.record.member" list="ctrl.Lists.Member" label="Member" on-change="ctrl.MemberRole.changeMember(name);"></nac-select>
    

    and in the end in the nac-select:

    <select ng-model="$ctrl.field" ng-options="r as r.name for r in $ctrl.list | orderBy: 'name'" ng-required="$ctrl.req" ng-if="!$ctrl.list.processing" ng-change="$ctrl.onChange($ctrl.field)">
    

    or if you want to pass in object:

    <nac-select field="ctrl.MemberRole.record.member" list="ctrl.Lists.Member" label="Member" on-change="ctrl.MemberRole.changeMember({id, name});"></nac-select>
    

    then your changeMember can look like this:

    changeMember: function(obj){
            alert(`${obj.name} ${obj.id}`);
        }
    

    New fiddle: https://jsfiddle.net/pegla/7gd3m2k0/2/