13

I'm using angularJS. I have a few <select> elements on my page, each with its own ng-change, for example:

<select id="hairColorComponent" ng-model="hairColor"
        ng-options="option.name for option in hairColorData"
        ng-change="updateUserData()">

I want to be able to determine which DOM element got updated from within the updateUserData function, without having to manually specify it as a parameter for each ng-change attribute.

Is there an event, or caller or something similar that I can use within the context of updateUserData?

Hopefully something like ng-change="updateUserData(caller)"

Ronald Wildenberg
  • 31,634
  • 14
  • 90
  • 133
OpherV
  • 6,787
  • 6
  • 36
  • 55

2 Answers2

11

There's no (easy) way to do this by design. Angular controllers are supposed to be completely separate of the DOM, so if you find yourself needing to reference the DOM in them you're probably approaching things the wrong way.

If your HTML is

<select id="hairColorComponent" ng-model="hairColor"
        ng-options="option.name for option in hairColorData"
        ng-change="updateUserData()">

Then changing the select will change the value of $scope.hairColor in your controller. In updateUserData() just read its value and act accordingly.

If in your situation there's really no way to do it except referencing the DOM, you could do it by writing a custom directive. In general, direct DOM manipulation in Angular should be a last resort kind of measure though.

Ronald Wildenberg
  • 31,634
  • 14
  • 90
  • 133
Michael Low
  • 24,276
  • 16
  • 82
  • 119
  • That was what I was afraid of. I'm trying to get the ID of the DOM element to log which data was changed. How would you go about it differently then? `$watch` each data item separately? – OpherV Jun 09 '13 at 09:12
  • 1
    I'm not sure of your exact situation, but I found it's not even necessary to have an id on the element at all if you've got an ng-model as you can do everything with that instead. You could $watch, or have a separate ng-change method for each select. Neither are that DRY I know, but keeping the DOM and controllers separate makes life a lot easier for maintenace/testing in the long run. – Michael Low Jun 09 '13 at 09:20
2

Found this on google, I eventually solved my problem so here's my solution.

If you just need the ID, you could always just pass that as a parameter.

<select id="hairColorComponent" ng-model="hairColor"
        ng-options="option.name for option in hairColorData" 
        ng-change="updateUserData('hairColorComponent')">

Still not super clean, but it solved my problem. Since I actually needed the dom element, I then used jQuery to get the element.

$scope.updateUserData = function (id) {
    var element = jQuery('#'+id);
};

(For those wondering, I'm doing my best with converting legacy code that "magically" saves user settings on pages all over the website.)

Loren
  • 9,783
  • 4
  • 39
  • 49