AngularJS revert selected value of control nested in ng-repeat on dialog cancel

367 Views Asked by At

I want to revert a select tag value that is inside a ng-repeat after cancelling a confirm dialog.

Here is what I have so far:

Relevant HTML:

<table>
  <tbody>
    <tr ng-repeat="application in rows">
      <td>
        <select
                ng-model="application.selectedVersion"
                ng-options="apk.versionName for apk in application.versions | orderBy : 'id' : true"
                ng-init="application.selectedVersion=application.versions.filter(currentVersion, application.apkUpdates)[0]"
                ng-change="selectionChanged(application, '{{application.selectedVersion}}')"
                style="padding:0 1em;" />
      </td>
    </tr>
  </tbody>
</table>

Javascript logic:

$scope.selectionChanged = function(application, previousVersion) {
  var dialog = confirm('Change version?');

  if (dialog) {
    console.log('change version confirmed');
  } else {
    application.selectedVersion = previousVersion;
  }
};

Passing '{{application.selectedVersion}}' to the function instead of application.selectedVersion passes the previously selected value instead of the current (explained here: https://stackoverflow.com/a/45051464/2596580).

When I change the select value, perform the dialog interaction and cancel it I try to revert the value by setting application.selectedVersion = angular.copy(previousVersion);. I can see the value is correct by debugging the javascript but the select input is set to blank instead of the actual value.

What am I doing wrong?

JSFiddle demo: https://jsfiddle.net/yt4ufsnh/

2

There are 2 best solutions below

4
Pankaj Parkar On BEST ANSWER

You have to correct couple of things in your implementation

  1. When you pass '{{application.selectedVersion}}' to selectionChanged method, it becomes raw string. When you re assigns back to the application.selectedVersion you have to first parse that previousVersion to JSON using JSON.parse method
  2. Use track by apk.id on ng-options collection. This is needed because the JSON parsed object is not recognized as the same instance of the object used to build the select, so this works as if overriding an intrinsic equals function to use only its id property

Final Version

ng-options="apk.versionName for apk in (application.versions | 
                                           orderBy : 'id' : true) track by apk.id" 

Code

$scope.selectionChanged = function(application, previousVersion) {
    var dialog = confirm('Change version?');
    if (dialog) {
      console.log('change version confirmed');
    } else {
      application.selectedVersion = previousVersion ? JSON.parse(previousVersion) : null;
    }
};

Updated Fiddle

1
Danizavtz On

if you just remove the else condition from your javascript code, you can reach the behaviour you need.

Your final code should be:

$scope.selectionChanged = function(application, previousVersion) {
  var dialog = confirm('Change version?');

  if (dialog) {
    console.log('change version confirmed');
  }
};