Binding selects without an "empty" <option>

Hey guys. Not sure if this is a bug or not, but Aurelia won’t bind a select value when there’s only 1 item in the list like follows:

<select class="form-control" id="PageTypeId" name="PageTypeId" value.bind="pageModel.pageTypeId">
    <option value="0bedc229-2280-46fa-b157-bce4f1cddeaa">Standard Page</option>
</select>

The backing property (in this case: pageModel.pageTypeId) doesn’t get the value from the only option there. The only way to make this work is to add a new “empty” option as follows:

<select class="form-control" id="PageTypeId" name="PageTypeId" value.bind="pageModel.pageTypeId">
    <option value="">Select</option>
    <option value="0bedc229-2280-46fa-b157-bce4f1cddeaa">Standard Page</option>
</select>

Then make the user have to choose. Is there a way around this? I don’t want to add the “Select” option in there. It should just bind to the first option in the list automatically. Is there some option I can set for that behaviour or do I log this as an issue?

It looks like aurelia select did something special with repeator, if you do following, it will populate the id as expected.

<select class="form-control" id="PageTypeId" name="PageTypeId" value.bind="pageModel.pageTypeId">
    <option repeat.for="opt of options" model.bind="opt.value">${opt.label}</option>
</select>
options = [
  {label: "Standard Page", value: "0bedc229-2280-46fa-b157-bce4f1cddeaa"}
];

Thanks, @huochunpeng, but the problem with that is in some cases (including this one), I am using “Html Helpers” in ASP.NET .cshtml files and my framework has many reusable helpers I would like to keep using. In this case, the <select> I was referring to is actually generated from some code as follows:

@Html.Framework().PageTypesDropDownList(
    "PageTypeId",
    htmlAttributes: new Dictionary<string, object>
    {
        { "class", "form-control" },
        { "value.bind", "pageModel.pageTypeId" }
    })

I have quite a few of these helpers and I don’t want to have to rewrite everything if I don’t have to. Surely there must be another way to make Aurelia use the first option that is there.

UPDATE: @huochunpeng, I have just tried your way and even that doesn’t work. If there’s only 1 item in the list, it will not bind. When I post the data, pageModel.pageTypeId is ALWAYS empty and does not set to the only available option, as it should.

Something is definitely wrong here, because I also just tried the following to no avail:

<select class="form-control" id="PageTypeId" name="PageTypeId" value.bind="pageModel.pageTypeId">
    <option value="" disabled="disabled">Select...</option>
    <option repeat.for="option of pageTypes" value.bind="option.value">${option.label}</option>
</select>

It displays just fine and I put in an empty option, but set it as disabled. However, the property I am binding to (pageModel.pageTypeId) does NOT get set. The only way I can get this to work is to do as above, but without making the empty option disabled. But then the user has to explicitly select an option, rather than the first option be automatically selected. That blows. Surely this must be a bug, right? If I am missing something here, please enlighten me. Otherwise, I will open it as an issue. I assume it would need to be logged in the aurelia/binding repo, right?

I got no idea what’s wrong.

But you can be proactive. Pre-populate the value of pageModel.pageTypeId to the first one available, so select's value binding doesn’t need to extra work.

I agree, a GitHub issue is a good idea.

I tried a bit in my code and found that this will work - the browser selects the first available option and it is also set as value timestamp:

<select value.bind="timestamp">
    <option model.bind="undefined" disabled>Select timestamp...</option>
    <option repeat.for="ts of timestamps" model.bind="ts.Timestamp">${ts.Timestamp}</option>
</select>

The difference seems to be the model.bind="undefined" for the disabled option.