【问题标题】:AngularJS revert selected value of control nested in ng-repeat on dialog cancelAngularJS在对话框取消时恢复嵌套在ng-repeat中的控件的选定值
【发布时间】:2023-12-09 05:03:01
【问题描述】:

我想在取消确认对话框后恢复 ng-repeat 内的 select 标记值。

这是我目前所拥有的:

相关 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 逻辑

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

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

'{{application.selectedVersion}}' 传递给函数而不是application.selectedVersion 传递先前选择的值而不是当前值(此处解释:https://*.com/a/45051464/2596580)。

当我更改选择值时,执行对话交互并取消它我尝试通过设置application.selectedVersion = angular.copy(previousVersion); 来恢复该值。我可以通过调试 javascript 看到该值是正确的,但选择输入设置为空白而不是实际值。

我做错了什么?

JSFiddle 演示:https://jsfiddle.net/yt4ufsnh/

【问题讨论】:

    标签: javascript angularjs angularjs-ng-repeat angularjs-ng-model angularjs-ng-init


    【解决方案1】:

    你必须在你的实现中纠正几件事

    1. 当您将'{{application.selectedVersion}}' 传递给selectionChanged 方法时,它会变成原始string。当您重新分配回application.selectedVersion 时,您必须首先使用JSON.parse 方法将previousVersion 解析为JSON
    2. ng-options 集合上使用track by apk.id。这是必需的,因为 JSON 解析的对象不被识别为用于构建选择的对象的同一实例,因此这就像覆盖内部 equals 函数以仅使用其 id 属性一样工作

    最终版

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

    代码

    $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

    【讨论】:

    • 这适用于实际设置选择输入上的值,但它设置的是当前值。我想要的是设置以前的值(即取消 ng-change 更新以查看)。我编辑了问题以澄清这个细节。
    • @Netherdan 你能看看更新的答案吗?
    • 当我注意到您的更新时,我发布了相同的答案。原因是 JSON 解析的对象不等于用于构建选择的对象(即JSON.parse(previousVersion) === application.versions[previousVersionIndex] 返回 false),因此它不会将其识别为同一个实例。 track by 子句强制通过 id 值跟踪对象,因此即使是原始 JSON.parse("{id:x}") 也可以,但我不需要也不会这样做。您的解决方案按预期工作。谢谢!
    • @Netherdan 随时编辑答案:) 我会接受编辑
    【解决方案2】:

    如果你只是从你的 javascript 代码中删除 else 条件,你可以达到你需要的行为。

    你的最终代码应该是:

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

    【讨论】:

    • 然后更新值(我在确认对话框之前选择的值设置为当前值)。我想要的是将此值恢复为先前选择的值。