Rendering a select menu with a pre-selected item with jade

11,063 views
Skip to first unread message

Ryan Schmidt

unread,
Sep 24, 2011, 6:27:50 PM9/24/11
to expre...@googlegroups.com
I must be doing something stupid but I'm having a heck of a time getting a particular item to be pre-selected in an html <select> menu, and I wasn't able to find an example to follow.

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.

Shawn Meng

unread,
Sep 25, 2011, 2:31:01 AM9/25/11
to expre...@googlegroups.com
I think you can do it like this.

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)

weibo.com/mengxy

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

vision media [ Tj Holowaychuk ]

unread,
Sep 25, 2011, 12:14:27 PM9/25/11
to expre...@googlegroups.com
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)

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
--
Tj Holowaychuk
Vision Media
President & Creative Lead

Ryan Schmidt

unread,
Sep 25, 2011, 7:05:03 PM9/25/11
to expre...@googlegroups.com

On Sep 25, 2011, at 11:14, vision media [ Tj Holowaychuk ] wrote:

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


TJ Holowaychuk

unread,
Sep 25, 2011, 7:06:57 PM9/25/11
to expre...@googlegroups.com
if mongoose doesn't already use .id it might be nice to have that equivalent to ._id.toString() at all times

-- 
TJ Holowaychuk

Dan MacTough

unread,
Sep 25, 2011, 10:01:50 PM9/25/11
to expre...@googlegroups.com
Mongoose gives you the virtual '.id' by default in recent versions. You don't need to define it yourself anymore.

Ryan Schmidt

unread,
Sep 26, 2011, 2:03:34 AM9/26/11
to expre...@googlegroups.com

On Sep 25, 2011, at 21:01, Dan MacTough wrote:

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


Dan MacTough

unread,
Sep 26, 2011, 7:58:40 AM9/26/11
to expre...@googlegroups.com
I'm not sure if it's documented -- I can't find it in the docs. I've been mucking around a lot in the source and the tests. I stumbled across it in one of the tests, I think. Basically, it gives you '.id' for free, but you can override it if you want (or, more likely, it will just keep using the virtual in your model until you realize you don't need it there any more). ;-)
Reply all
Reply to author
Forward
0 new messages