Cake_Seller Cake_Seller - 3 months ago 14
Javascript Question

How to set value to model in AngularJS using select with array of objects

I'm new to AngularJS and I'm trying to solve one problem in most elegant way.

I have list that comes from server and used as the source for

select
tag's
option
's in my application. Lets assume that it's a list of authors which looks like this:

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


Also I have book model which comes from and saved to server. One of book's properties is
author
which can be choosen by user from
select
dropdown. When book model is saved or fetched from server it's
author
field is represented as integer. Here is an example of how book model should be saved on server and how it looks when fetched:

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


book is represented as Angular's
$resource
in my application so whenever I want to save book model I just call it's save method.

To implement this logic I have tried to use
select
with
ng-options
directive, like this:

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


But the problem with this approach is that when I pick author from drop down the value of
author
property is set to
{ id: 2, name: 'Jack London' }
but I need it to be an author's id.

Here is a Fiddle that illustrates my problem. Try to select different values in drop down. Below the drop down you will see updated value of
bookModel.author
. I need it to be an author's id integer, not the object. So whenever I choose Jack London in drop down I need the value of
bookModel.author
to be
2
, not
{ id: 2, name: 'Jack London' }
. Otherwise I need do manipulations with data whenever book model comes from server and before I save it. I suppose that there can be a better way. Maybe it is something that can be achieved with
ng-options
directive?

I have tried do it this way:

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


It's a bit closer but this way
bookModel.author
's value will be a string, not integer.

Also I know that I can set
transformRequest
and
transformResponse
functions for book $resource which will transform data to appropriate format. But maybe there is a better way?

Will appreciate any help!

Answer

You should use author.id as author.name on your ng-options like so:

<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>

Or, if you want the author's name:

<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>

UPDATE 1

Updated your fiddle

Comments