Repository: angular/angular.js

Issue #9867: Function in ng-change is fired before input is touched.
Created: 2014-11-01T00:02:17Z
Today I wanted to "upgrade" to 1.3.1.
Every piece of my app is working but ng-change not anymore.
My function "showPriority()" is called when template is rendering as many times as is items in an object speakers (deferred ajax result from laravel api).
It was working fine (function is called only when I will change the value of input) in 1.3.0-beta.19, but not in 1.3.0-rc.0+ (for 4 items is called 4x, when i will change the value +1x...).
Is there any difference in ngChange?
<div data-ng-repeat="item in speakers | orderBy:sortBy:reverse">
  <input type="text" data-ng-model="item.priority" data-ng-change="showPriority()">
</div>

Duplicate issue #9918: ngChange for <select> after 1.3.0 rc0 now fires when value is undefined
Created: 2014-11-05T05:24:38Z
In our application prior to 1.3.0 rc1 the ng-change event was not being fired when our  was first displayed. Now it is being fired and when we check the value of the variable used for model then it has a value of undefined.
This happens only when a form is first displayed. All versions including and prior to rc0 are okay. All versions after fire the ngChange when the model value is still undefined.
Here is the code that we are using:
<select ng-model="home.modal.topicId"
        ng-change="ctrl.modalTopicChanged()"
        ng-options="item.id as item.name for item in home.modal.option.topics.data"
        ng-required="true">
        <option style="display: none;" value="">Select Topic</option>
</select>

Producing a stack trace when the function code attempts to use an undefined value for home.modal.topicId. This happens only for 1.3.0 rc1 and later versions:
TypeError: Cannot read property 'dataMap' of undefined
    at AdminProblemController.modalTopicChanged (http://127.0.0.1:17315/Content/app/admin/controllers/ProblemController.js:109:114)
    at $parseFunctionCall (http://127.0.0.1:17315/Scripts/angular.js:11387:18)
    at Scope.$get.Scope.$eval (http://127.0.0.1:17315/Scripts/angular.js:13276:28)
    at http://127.0.0.1:17315/Scripts/angular.js:19888:13
    at http://127.0.0.1:17315/Scripts/angular.js:19499:9
    at forEach (http://127.0.0.1:17315/Scripts/angular.js:331:20)
    at $$writeModelToScope (http://127.0.0.1:17315/Scripts/angular.js:19497:5)
    at writeToModelIfNeeded (http://127.0.0.1:17315/Scripts/angular.js:19490:14) 
    at http://127.0.0.1:17315/Scripts/angular.js:19484:9
    at validationDone (http://127.0.0.1:17315/Scripts/angular.js:19420:9) 


I checked and it would appear there were significant changes to a code area in rc1 that I assume are now causing us this problem. In particular there were many changes around the area of code below:
**
   * @ngdoc method
   * @name ngModel.NgModelController#$commitViewValue
   *
   * @description
   * Commit a pending update to the `$modelValue`.
   *
   * Updates may be pending by a debounced event or because the input is waiting for a some future
   * event defined in `ng-model-options`. this method is rarely needed as `NgModelController`
   * usually handles calling this in response to input events.
   */
  this.$commitViewValue = function() {
    var viewValue = ctrl.$viewValue;

    $timeout.cancel(pendingDebounce);

    // If the view value has not changed then we should just exit, except in the case where there is
    // a native validator on the element. In this case the validation state may have changed even though
    // the viewValue has stayed empty.
    if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
      return;
    }
    ctrl.$$lastCommittedViewValue = viewValue;

    // change to dirty
    if (ctrl.$pristine) {
      ctrl.$dirty = true;
      ctrl.$pristine = false;
      $animate.removeClass($element, PRISTINE_CLASS);
      $animate.addClass($element, DIRTY_CLASS);
      parentForm.$setDirty();
    }
    this.$$parseAndValidate();
  };

  this.$$parseAndValidate = function() {
    var parserValid = true,
        viewValue = ctrl.$$lastCommittedViewValue,
        modelValue = viewValue;
    for(var i = 0; i < ctrl.$parsers.length; i++) {
      modelValue = ctrl.$parsers[i](modelValue);
      if (isUndefined(modelValue)) {
        parserValid = false;
        break;
      }
    }
    if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
      // ctrl.$modelValue has not been touched yet...
      ctrl.$modelValue = ngModelGet();
    }
    var prevModelValue = ctrl.$modelValue;
    var allowInvalid = ctrl.$options && ctrl.$options.allowInvalid;
    if (allowInvalid) {
      ctrl.$modelValue = modelValue;
      writeToModelIfNeeded();
    }
    ctrl.$$runValidators(parserValid, modelValue, viewValue, function() {
      if (!allowInvalid) {
        ctrl.$modelValue = ctrl.$valid ? modelValue : undefined;
        writeToModelIfNeeded();
      }
    });

    function writeToModelIfNeeded() {
      if (ctrl.$modelValue !== prevModelValue) {
        ctrl.$$writeModelToScope();
      }
    }
  };

  this.$$writeModelToScope = function() {
    ngModelSet(ctrl.$modelValue);
    forEach(ctrl.$viewChangeListeners, function(listener) {
      try {
        listener();
      } catch(e) {
        $exceptionHandler(e);
      }
    });
  };


I would like to know if this is intended functionality. I see no mention of this in the changes so I assume it may be a change that was not intended but that has not been caught in testing.

Closing comment (2014-11-05T13:27:23Z): I don't think this is related to #9867, but you should create a reproduction on http://plnkr.co so we can take a look. #9867 has to do with a defined model value being transformed into a string, therefore being considered changed, even though the user didn't touch it.