AngularJS and select boxes

I've been noodling around with AngularJS this week, primarily for its two-way data binding capability which makes for a far more interactive web page. I know it has much more power than this - perhaps these power are for another day.

In any case, I spent the best part of two days on what seems to be a common problem for people trying to use AngularJS to create select boxes in forms. More specifically, the problem is selecting the default item in a select box.

I wanted to create a select box from my client data (JSON) like this ...

[
{
id: "1",
name: "Tester 01",
inactive: "0",
created_at: "2014-01-09 20:30:18",
updated_at: "2014-01-09 20:30:18"
},
{
id: "2",
name: "Tester 02",
inactive: "0",
created_at: "2014-01-09 20:30:18",
updated_at: "2014-01-09 20:30:18"
}
]

... and to choose the default select box item with related (by use of a client_idcontract data like this ...

{
id: "1",
client_id: "1",
contact_id: "1",
reference: "JOB.0000001",
po: "1111111",
name: "Job One",
notes: "Test notes one",
selected_phase: "1",
created_at: "2014-01-09 20:30:18",
updated_at: "2014-01-09 20:30:18"
}

The official Angular documentation on creating select boxes suggest an approach in line with that shown below -

<select ng-model="contracts.client_id" ng-options="client.name for client in clients"></select><br>

I expected that contracts.client_id (which is equal to 1) in the contracts data to match off against the id in the clients data, in this example, client 'Tester 01', and have my select box default to 'Tester 01'.

That didn't happen.

In reality, the answer was simple. And the answer was to be found quite easily online, but because I did not understand the answers given I did not realise they were the solution to my issue. So I will try to do a better job of explaining it here.

It turns out the official approach above was missing a snippet or two of code. Check this out -

<select ng-model = "contracts.client_id" ng-options = "client.id as client.name for client in clients"></select>

Now, client.id sets the option value of the select box - the thing that gets looked up when setting a default value and client.name is the bit that shows up on the web page. contracts.client_id (which we know is equal to 1) will now match off against one of the option values in the select box and choose it as the default.

My guess is that without the client.id as bit, the option value is the same as the text output on the web page - 'Tester 01' in this example - which does not equal contracts.client_id (which is equal to 1) or any other value in the contracts data and nothing is selected by default.

Also be wary that some non-official documentation suggests that implementation should look something like this -

<select ng-model="selected_client" ng-options="client for client in clients"></select><br>

Of course, for me this would not work as now AngularJS will be looking for a whole chunk of JSON to match off before it will select a default item, which might look a bit like this ...

[
id: "1",
name: "Tester 01",
inactive: "0",
created_at: "2014-01-09 20:30:18",
updated_at: "2014-01-09 20:30:18"
]

... which in no way is equal to contracts.client_id (which is equal to 1). In this case, I tried to produce different JSON and I used a tip that is prevalent on the web which involved creating a subset of client data from the full set of data (using something like selected_client = clients[0]). Yeah, that was never going to work for me.

Anyway, I hope this saves you a bit of pain.