AngularJS возвращает выбранное значение элемента управления, вложенного в ng-repeat, при отмене диалога

Я хочу вернуть значение тега select, которое находится внутри ng-repeat, после отмены диалогового окна подтверждения.

Вот что у меня есть до сих пор:

Соответствующий 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://stackoverflow.com/a/45051464/2596580).

Когда я изменяю выбранное значение, выполняю диалоговое взаимодействие и отменяю его, я пытаюсь вернуть значение, установив application.selectedVersion = angular.copy(previousVersion);. Я вижу, что значение правильное, отлаживая javascript, но для ввода выбора установлено значение пустое, а не фактическое значение.

Что я делаю не так?

Демонстрация JSFiddle: https://jsfiddle.net/yt4ufsnh/


person Netherdan    schedule 13.09.2018    source источник


Ответы (2)


Вы должны исправить пару вещей в своей реализации

  1. Когда вы передаете метод '{{application.selectedVersion}}' методу selectionChanged, он становится необработанным string. Когда вы повторно назначаете обратно application.selectedVersion, вы должны сначала проанализировать это previousVersion до JSON, используя метод JSON.parse.
  2. Используйте track by apk.id в коллекции ng-options. Это необходимо, потому что проанализированный объект 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;
    }
};

Обновленный скрипт

person Pankaj Parkar    schedule 13.09.2018
comment
Это работает для фактической установки значения на входе select, но устанавливает текущее значение. Я хочу установить предыдущее значение (т.е. отменить обновление ng-change для просмотра). Я отредактировал вопрос, чтобы уточнить эту деталь. - person Netherdan; 13.09.2018
comment
@Netherdan Не могли бы вы взглянуть на обновленный ответ, пожалуйста? - person Pankaj Parkar; 13.09.2018
comment
Я публиковал тот же ответ, когда заметил ваше обновление. Причина этого в том, что проанализированный объект JSON не равен объекту, используемому для построения выбора (т. е. JSON.parse(previousVersion) === application.versions[previousVersionIndex] возвращает false), поэтому он не распознает его как один и тот же экземпляр. Предложение track by заставляет отслеживать объект по значению id, поэтому, возможно, сработает даже необработанный JSON.parse({id:x}), но мне это не нужно и я никогда не буду этого делать. Ваше решение работает так, как ожидалось. Спасибо! - person Netherdan; 13.09.2018
comment
@Netherdan не стесняйтесь редактировать ответ :) Я приму редактирование - person Pankaj Parkar; 14.09.2018

если вы просто удалите условие else из своего кода javascript, вы можете достичь нужного вам поведения.

Ваш окончательный код должен быть:

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

  if (dialog) {
    console.log('change version confirmed');
  }
};
person Danizavtz    schedule 13.09.2018
comment
Затем значение обновляется (значение, которое я выбрал перед диалоговым окном подтверждения, устанавливается в качестве текущего значения). Я хочу вернуть это значение к ранее выбранному. - person Netherdan; 13.09.2018