The <datalist>
element can be used to create a HTML-only "type-to-select" drop-down list (aka combobox with input enabled).
The elements with the <datalist>
tag are of type <option>
, just like those that would be in a <select>
list, which is supported by the asp-items
Razor tag helper.
e.g. it would be great to be able to turn
<select asp-for="Customer" asp-items="Customers"></select>
into
<input list="customers" asp-for="Model.Customer" />
<datalist id="customers" asp-items="Model.Customers"></datalist>
But perhaps it would be necessary for the tags to be coalesced into one, so that one need not type out and match the id
tag, in which case it might look something like this:
<input asp-for="Model.Customer" asp-items="Model.Customers" />
Yes please allow us to do:
<input type="text" name="example" list="exampleList">
<datalist id="exampleList">
<option value="A">
<option value="B">
</datalist>
This would require no JavaScript, allows users to select an item or add one if missing. Very useful in admin panels!!
Can I Use information: https://caniuse.com/#feat=datalist
see also here: https://github.com/aspnet/Mvc/issues/8322
Thanks for contacting us, @mqudsi.
Feel free to send us a PR for this and we'd happily consider it.
I would be willing to give this a shot if no one has started work on it yet.
@mkArtakMSFT or @NTaylorMullen does it make sense for the tag helper to generate both the input & the datalist?
I feel it does. If that assumption is correct, the datalist element requires an id attribute and the input element requires a list attribute that matches. Is there a pattern established for defining how to name that matching attribute?
@mkArtakMSFT or @NTaylorMullen does it make sense for the tag helper to generate both the input & the datalist?
Good question. I'd imagine this would sit on the InputTagHelper
or the SelectTagHelper
given its intended functionality. @danroth27 any opinion?
@NTaylorMullen sorry for the late reply. I was waiting for @danroth27 to throw in some feedback & then I never got back to it.
When you say "sit on the InputTagHelper
or SelectTagHelper
" can you clarify what you mean & how you think it should be implemented by a user who wants to create a datalist?
can you clarify what you mean & how you think it should be implemented by a user who wants to create a datalist?
I was simply referencing @mqudsi's initial comment where something like this can be implemented in two different ways:
<select asp-for="Customer" asp-items="Customers"></select>
OR<input asp-for="Model.Customer" asp-items="Model.Customers" />
Would an attribute be used on the model property to have the input or select render as a datalist or how would you specify you want it rendered as a datalist?
I was thinking of making a <datalist asp-for"Customer" asp-items="Customers"></datalist>
but I'm open to ideas, especially if they're simpler.
Would an attribute be used on the model property to have the input or select render as a datalist or how would you specify you want it rendered as a datalist?
Honestly not sure, lots of different ways you could do it. Would have to experiment to see which way fit best. @DamianEdwards do you have any opinions here?
Usually I'd shoot for composition over aggregation for Tag Helpers, i.e. make <datalist asp-for="Model.State" asp-items="Model.StateItems">
rather than something that changes <input />
to render the list as well, as that makes it hard to style, modify, etc. But, in this case, it seems <datalist>
has no visual representation of its own that's styleable. In fact, it has none of its own attributes at all, only supporting the global attributes available to all elements, and I'm not aware of use cases that require setting them.
So, it might make the most sense to simply augment the <input />
element with support for something like asp-items
which if set would then output the <datalist>
. The only that gives me pause is the ability to statically add <option>
elements to the <datalist>
beyond the model passed, like we support for <select>
.
Perhaps we need to support both models?
So, I'd be shooting for consumption to look something like this:
<input asp-for="State" />
<datalist asp-for="State" asp-items="Model.StateItemsList">
<option>I can put things in here too and they merge into the list, like select items do</option>
</datalist>
The more I look into this, the more scenarios appear and thus the more complicated it seems :smile:
Some baseline points (facts, hopefully):
<datalist>
has no rendering and should never be visual in its own right (so no need to support styling or other attributes on its element tag)<datalist>
can be used by multiple controls<datalist>
it wishes to use via the list
attribute containing the id
of the <datalist>
elementlist
attribute is only support on the <input>
element (as far as I can tell anyway)<option>
elements nested under a <datalist>
can only specify the value
attribute. None of the other attributes typically associated with <option>
when using under a <select>
apply, e.g. selected
, etc.Anything provided by a Tag Helper would want to keep the above in mind and ensure it leads folks to the "pit of success" while not preventing scenarios that are supported by the underlying element behavior itself.
As a strawman, let's consider two main usage scenarios:
IEnumerable<string>
<option>
elements for a <datalist>
from a single IEnumerable<string>
For scenario 1, we add an asp-list
attribute (IEnumerable<string>
) to the <input />
element that generates a sibling <datalist>
with a derived id
(e.g. [InputFieldId-List]
) and sets the input
element's list
attribute to that id, e.g.
Model
public string State { get; set; }
public List<String> StateSuggestions => new List<string> { "VIC", "NSW", "QLD", "NT", "WA", "SA", "TAS", "ACT" }
CSHTML Source
<input asp-for="State" asp-list="Model.StateSuggestions" />
HTML Output
<input id="State" list="State.List" />
<datalist id="State.List">
<option value="VIC"></option>
<option value="NSW"></option>
<option value="QLD"></option>
<option value="NT"></option>
<option value="WA"></option>
<option value="SA"></option>
<option value="TAS"></option>
<option value="ACT"></option>
</datalist>
Scenario 2 supports slightly more advanced cases, including where folks want to reuse a single <datalist>
across multiple text fields, or mix statically declared option values with those from C# expression/model. For these cases, we add an asp-items
attribute (IEnumerable<string>
) to the <datalist>
element that generates the requisite <option>
elements after any existing content in the <datalist>
element as it's declared (i.e. it appends them). It wouldn't do anything to generate an id
attribute, e.g.
Model
public string FeelingMorning { get; set; }
public string FeelingAfternoon { get; set; }
public string FeelingEvening { get; set; }
public List<String> FeelingSuggestions => new List<string> { "Happy", "Sad", "Joyful", "Angry" }
CSHTML Source
<input asp-for="FeelingMorning" list="feelings" />
<input asp-for="FeelingAfternoon" list="feelings" />
<input asp-for="FeelingEvening" list="feelings" />
<datalist id="feelings" asp-list="Model.FeelingSuggestions" />
HTML Output
<input id="FeelingMorning" list="feelings" />
<input id="FeelingAfternoon" list="feelings" />
<input id="FeelingEvening" list="feelings" />
<datalist id="feelings">
<option value="Happy"></option>
<option value="Sad"></option>
<option value="Joyful"></option>
<option value="Angry"></option>
</datalist>
One could also statically declare options in the <datalist>
inline:
CSHTML Source
<input asp-for="FeelingMorning" list="feelings" />
<input asp-for="FeelingAfternoon" list="feelings" />
<input asp-for="FeelingEvening" list="feelings" />
<datalist id="feelings" asp-list="Model.FeelingSuggestions">
<option value="Stressed"></option>
</datalist>
HTML Output
<input id="FeelingMorning" list="feelings" />
<input id="FeelingAfternoon" list="feelings" />
<input id="FeelingEvening" list="feelings" />
<datalist id="feelings">
<option value="Stressed"></option>
<option value="Happy"></option>
<option value="Sad"></option>
<option value="Joyful"></option>
<option value="Angry"></option>
</datalist>
Why not having both options:
<input asp-for="FeelingEvening" asp-list="Model.FeelingSuggestions"/>
as well as:
<input asp-for="FeelingEvening" asp-list="Model.FeelingSuggestions"/>
<input asp-for="FeelingEvening" asp-list="Model.FeelingSuggestions"/>
<datalist asp-list="Model.FeelingSuggestions" />
I am a beginner with ASP.net Core, so I can not say how feasible it is to implement this, but it would be flexible and comprehensive...
Most helpful comment
The more I look into this, the more scenarios appear and thus the more complicated it seems :smile:
Some baseline points (facts, hopefully):
<datalist>
has no rendering and should never be visual in its own right (so no need to support styling or other attributes on its element tag)<datalist>
can be used by multiple controls<datalist>
it wishes to use via thelist
attribute containing theid
of the<datalist>
elementlist
attribute is only support on the<input>
element (as far as I can tell anyway)<option>
elements nested under a<datalist>
can only specify thevalue
attribute. None of the other attributes typically associated with<option>
when using under a<select>
apply, e.g.selected
, etc.Anything provided by a Tag Helper would want to keep the above in mind and ensure it leads folks to the "pit of success" while not preventing scenarios that are supported by the underlying element behavior itself.
Strawman Spec
As a strawman, let's consider two main usage scenarios:
IEnumerable<string>
<option>
elements for a<datalist>
from a singleIEnumerable<string>
Scenario 1
For scenario 1, we add an
asp-list
attribute (IEnumerable<string>
) to the<input />
element that generates a sibling<datalist>
with a derivedid
(e.g.[InputFieldId-List]
) and sets theinput
element'slist
attribute to that id, e.g.Model
CSHTML Source
HTML Output
Scenario 2
Scenario 2 supports slightly more advanced cases, including where folks want to reuse a single
<datalist>
across multiple text fields, or mix statically declared option values with those from C# expression/model. For these cases, we add anasp-items
attribute (IEnumerable<string>
) to the<datalist>
element that generates the requisite<option>
elements after any existing content in the<datalist>
element as it's declared (i.e. it appends them). It wouldn't do anything to generate anid
attribute, e.g.Model
CSHTML Source
HTML Output
One could also statically declare options in the
<datalist>
inline:CSHTML Source
HTML Output