Как установить значение для модели в AngularJS, используя выбор с массивом объектов

Я новичок в AngularJS и пытаюсь решить одну проблему самым элегантным способом.

У меня есть список, который поступает с сервера и используется в качестве источника для тегов select option в моем приложении. Предположим, что это список авторов, который выглядит так:

[
  { id: 1, name: 'Mark Twain' },
  { id: 2, name: 'Jack London' },
  { id: 3, name: 'Ernest Hemingway' }
]

Также у меня есть модель книги, которая получена и сохранена на сервере. Одним из свойств книги является author, которое пользователь может выбрать из раскрывающегося списка select. Когда модель книги сохраняется или загружается с сервера, ее поле author представляется как целое число. Вот пример того, как модель книги должна быть сохранена на сервере и как она выглядит при извлечении:

{
  id: 324,
  title: 'Martin Eden',
  author: 2
}

book в моем приложении представлен как $resource Angular, поэтому всякий раз, когда я хочу сохранить модель книги, я просто вызываю ее метод сохранения.

Чтобы реализовать эту логику, я попытался использовать select с директивой ng-options, например:

<select ng-options="author as author.name for author in authors track by author.id" ng-model="bookModel.author"></select>

Но проблема с этим подходом заключается в том, что когда я выбираю автора из раскрывающегося списка, значение свойства author устанавливается равным { id: 2, name: 'Jack London' }, но мне нужно, чтобы это был идентификатор автора.

Вот Fiddle, иллюстрирующий мою проблему. Попробуйте выбрать другие значения в раскрывающемся списке. Под раскрывающимся списком вы увидите обновленное значение bookModel.author. Мне нужно, чтобы это было целое число идентификатора автора, а не объект. Поэтому всякий раз, когда я выбираю Джек Лондон в раскрывающемся списке, мне нужно, чтобы значение bookModel.author было 2, а не { id: 2, name: 'Jack London' }. В противном случае мне нужно выполнять манипуляции с данными всякий раз, когда модель книги поступает с сервера и до ее сохранения. Я полагаю, что может быть лучший способ. Может быть, этого можно добиться с помощью директивы ng-options?

Я пытался сделать это следующим образом:

<select ng-model="bookModel.author">
  <option ng-repeat="author in authors" value="{{author.id}}">{{author.name}}</option>
</select>

Это немного ближе, но таким образом значение bookModel.author будет строкой, а не целым числом.

Также я знаю, что могу установить функции transformRequest и transformResponse для book $resource, которые будут преобразовывать данные в соответствующий формат. Но, может быть, есть лучший способ?

Будем признательны за любую помощь!


person Cake_Seller    schedule 09.08.2016    source источник


Ответы (1)


Вы должны использовать author.id as author.name на своем ng-options следующим образом:

<div ng-app="app">
  <div ng-controller="testController">
    <select ng-options="author.id as author.name for author in authors track by author.id" ng-model="bookModel.author"></select>
    <pre>{{bookModel.author | json}}</pre>
  </div>
</div>

Или, если вы хотите имя автора:

<div ng-app="app">
  <div ng-controller="testController">
    <select ng-options="author.name as author.name for author in authors track by author.id" ng-model="bookModel.author"></select>
    <pre>{{bookModel.author | json}}</pre>
  </div>
</div>

ОБНОВЛЕНИЕ 1

Обновлена ​​ваша скрипта.

person lenilsondc    schedule 09.08.2016
comment
Это отлично работает, когда я выбираю автора из выпадающего списка. Но что, если свойство author уже имеет значение? Я думал, что в этом случае он должен отображаться как выбранный в раскрывающемся списке, но это не так. Вот скрипка. Как видите, в select не выбрана ни одна опция. - person Cake_Seller; 09.08.2016
comment
Другой парень помог мне решить эту последнюю проблему. Все, что мне нужно, это удалить часть track by author.id из директивы ng-options. Вот финальная скрипка. Большое спасибо за твою помощь! - person Cake_Seller; 09.08.2016