I'm building an edit form for a thing. The thing contains a user field (the user who owns that thing). So in my route I findOne() the thing with mongoose, populate() the user field, find() the list of all users, and render() the view, sending it "thing" and "users" as locals. The view contains this:
div
label User:
select(name='thing[user]')
option(value='')
each user in users
option(value=user._id, selected=(user._id==thing.user._id))= user.username
I can print out "user._id" and "thing.user._id" in the view, and they contain the right values. But the entry in the menu corresponding to the thing's user never gets marked as "selected" ('selected="selected"' does not get added to any item).
Can anyone see what I'm doing wrong? Or is there a different way I should be doing this? Thanks.
div
label User:
select(name='thing[user]')
option(value='')
each user in users
- var select=null; if (user._id == thing.user._id) select='selected';
option(value=user._id, selected=select)= user.username
Frontend Engineer @ imeigu (www.imeigu.com) iChinaStock (www.ichinastock.com)
> --
> You received this message because you are subscribed to the Google Groups "Express" group.
> To post to this group, send email to expre...@googlegroups.com.
> To unsubscribe from this group, send email to express-js+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/express-js?hl=en.
>
> with jade a boolean can indicate if the value is mirrored, for example when non-dynamic:
>
> option(value='foo', selected)
>
> or
>
> option(value='foo', selected=true)
Right, I realized already that if I say 'option(selected=true)' then Jade will output 'selected="selected"' and if I say 'option(selected=false)' it will output nothing. So that wasn't the problem.
> so
>
> option(value='foo', selected=user._id == something._id)
>
> like you're doing should be correct as long as the input is what you expect
The problem was that the 'user._id==thing.user._id' comparison was always false. I've now realized this was because in mongodb / mongoose _id attributes are objects, not strings. If I switch the comparison to 'user._id.toString()==thing.user._id.toString()' it works.
This was not immediately apparent because when I would output them to debug them, they'd be shown as strings which were clearly the same string. But of course they're two different objects and so aren't "equal". I now understand why the "lmawa" tutorial had a virtual "id" field computed as a string representation of "_id".
http://dailyjs.com/2010/11/22/node-tutorial-4/ (under the heading "Mongo IDs")
So much of that tutorial (especially the early parts) has already been obsoleted in current versions of node / express / mongoose that I had assumed, since my other attempts to use _id directly had been successful, that this was another obsolete programming practice, but it appears not to be. Now that I've added a virtual id field, and switched to referring to id instead of _id, things are great.
UserSchema.virtual('user.id').get(function() {
return this._id.toString();
});
I'll add one of those to each of my models and I'll be set.
> Mongoose gives you the virtual '.id' by default in recent versions. You don't need to define it yourself anymore.
Oh thanks. I had no idea. Is that documented somewhere? I've probably not read every mongoose doc page yet but I didn't see that in any of the sections I read.