AngularJS, cancel ng-change

583 Views Asked by At

I followed a description from another answer in order to cancel ng-change on a select dropdown. The code should stop changing year if the user has filled out some numbers in week 53, if the year he switches to does not contain a week 53. This code works, but only the first time. Can anyone explain why? My guess is that it has something to do with changing the wrong scope, but since I cannot pass the scope as a parameter to ng-change I'm really not sure...

This is HTML:

<select data-ng-change="updateYear('{{Year}}');" data-ng-model="Year">
                        <option value="2012">2012</option>
                        <option value="2013">2013</option>
                        ...               
</select>

This is the controller:

$scope.updateYear = function (oldYear) {
    hasValuesInW53($scope.selectedProgram.Uid, function (hasW53Values) {
        var has54weeks = ['2015', '2020', '2026', '2032', '2037'];
        if ($.inArray(oldYear, has54weeks) > -1 && //old year has 53 weeks
            $.inArray($scope.Year, has54weeks) == -1 && //new year does not have 53 weeks
            hasW53Values //has values in W53
        ) {
            $scope.Year = oldYear;  
        }
        else {
            $scope.updateProgram();
        }
    }); 

This is what I do:

Switch 2020 to 2019 -> Works ok, the cancel code is triggered and GUI is changed back. Swotch 2020 to 2019 again -> Does not work. Cancel code is still triggered, but it's not reflected in GUI).

2

There are 2 best solutions below

1
Fakhar Ahmad Rasul On

My guess is, its because you are mixing angular and jquery and be ready to get unexpected results whenever you are doing that because angular is data driven and jquery is deals with the DOM elements directly. Try using angular.forEach or array.indexOf instead of $.inArray

0
Andreas Skagestad On

I found a dirty workaround in order to solve the problem. As suspected, in the original solution, the wrong scope is referenced, and I could not get the correct one since ng-change does not support passing $event where I can reference the correct scope. My workaround is adding ng-focus, storing the event, and use this to access the correct scope. Dirty, but works.

HTML:

<select data-ng-model="Year" data-ng-focus="yearFocusCallback($event)" data-ng-change="updateYear('{{Year}}');">
  <option value="2012">2012</option>
  <option value="2013">2013</option>
     ...            
</select> 

CONTROLLER:

$scope.yearChangeEvent = null;
$scope.yearFocusCallback = function ($event) {
    $scope.yearChangeEvent = $event;
};
$scope.updateYear = function (oldYear) {
    hasValuesInW53($scope.selectedProgram.Uid, function (hasW53Values) {
        var has54weeks = ['2015', '2020', '2026', '2032', '2037'];
        if ($.inArray(oldYear, has54weeks) > -1 && //old year has 53 weeks
            $.inArray($scope.Year, has54weeks) == -1 && //new year does not have 53 weeks
            hasW53Values //has values in W53
        ) {
            angular.element($scope.yearChangeEvent.target).scope().Year = oldYear;  
        }
        else {
            $scope.updateProgram();
        }
    });  
}