Associating a selection with an array of objects in Aurelia and matching by identifier

So, I have a list of all users that fills in the selection options.

<option repeat.for="user of userService.users"> ${user.firstName} ${user.lastName} </option> 

And I have an incoming group entry that has a list of users connected to it. I follow the cheat sheat instructions and bind them to the same model index.

 <select value.bind="group.users[0]"> <option repeat.for="user of userService.users" model.bind="user"> ${user.firstName} ${user.lastName} </option> </select> 

So, the incoming user in the group is identical to the incoming user in the list:

 { id: 123, firstName: 'Matt', lastName: 'Davis' } 

But when the group is loaded and attached to the view, the correct user is not selected from the selected one. Actually, I would expect this, since JavaScript would look for referential equality.

Ideally, I would like Aurelia to find that the incoming record is the same as above, and (a) search the list of equality checking options (b) that I defined in some extension (maybe in a filter?), ( c) select it from the list and (d) propagate this selection back to the record so that the record is now essentially synchronized.

I would prefer not to return to a trigger that manually does this because I will have many, many such options throughout the application.

I would agree, albeit sadly, for (a) and (c).

+8
javascript aurelia aurelia-binding
source share
1 answer

Define the matcher function (equalization):

 <select value.bind="group.users[0]" matcher.bind="userComparer"> <option repeat.for="user of userService.users" model.bind="user"> ${user.firstName} ${user.lastName} </option> </select> 
 export class Foo { ... userComparer = (userA, userB) => userA.id === userB.id; ... } 

Below is the original answer (before release 11/30/2015) ...

While this is not supported by the aurelia select binding, I would try something like this:

 <select value.bind="group.users[0] | userToId:userService.users"> <option repeat.for="user of userService.users" model.bind="user.id"> ${user.firstName} ${user.lastName} </option> </select> 
 export class UserToIdValueConverter { toView(user, users) { return user ? user.id : null; } fromView(id, users) { return users.find(u => u.id === id); } } 

Here's the plunker: http://plnkr.co/edit/15XHkQ?p=preview

You probably want to make a universal converter so that it can be reused throughout the application ... maybe something like this:

 export class ToIdValueConverter { toView(obj, idPropertyName, objs) { return obj ? obj[idPropertyName] : null; } fromView(id, idPropertyName, objs) { return objs.find(o => o[idPropertyName] === id); } } 
 <select value.bind="group.users[0] | toId:'id':userService.users"> <option repeat.for="user of userService.users" model.bind="user.id"> ${user.firstName} ${user.lastName} </option> </select> 

Stay tuned for this issue for inline framework support updates for this scenario.

+14
source share

All Articles