Open mqudsi opened 5 years ago
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...
I was just wondering if this is still being considered considering over 2 and a half years has passed since it was first requested. I have a need to add lots of datalists to a page so will need to use foreach loops instead but it would be much cleaner to use a razor helper.
We haven't had comments on this request in a long time but I agree it would still be mighty useful. While it's too late for .NET 6, we should include it in the list of items to be considered for .NET 7.
Meanwhile, I might have a go at implementing in my TagHelperPack project.
Thanks for the confirming it is still being considered.
In the end the workaround was not too bad but it would still be better:
<input asp-for="StaffRequest.RoomNumber" class="form-control" list="RoomNumberOptions" />
<datalist id="RoomNumberOptions">
@foreach (var item in ViewBag.RoomID) {
<option value="@item.Value">@item.Text</option>
}
</datalist>
Microsoft business politic is Miscrosoft business politic; Telerik would go bankrupt.
It looks like this has been pushed back to .NET 8 which is a shame as it seems like something quite basic everyone would find useful enabling people to reduce their code bases and facilitate more code re-use possibly too.
I think this would be a helpful feature if you need activity for it to be considered.
I was able to create a naive tag helper pretty easily as a workaround
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Something.TagHelpers;
[HtmlTargetElement("datalist", Attributes = ItemsAttributeName)]
public class DataListTagHelper : TagHelper {
private const string ItemsAttributeName = "asp-items";
public DataListTagHelper(IHtmlGenerator generator) {
Generator = generator;
}
protected IHtmlGenerator Generator { get; }
[HtmlAttributeNotBound]
[ViewContext]
public ViewContext ViewContext { get; set; }
[HtmlAttributeName(ItemsAttributeName)]
public IEnumerable<SelectListItem> Items { get; set; }
public override void Init(TagHelperContext context) {
ArgumentNullException.ThrowIfNull(context);
context.Items[typeof(DataListTagHelper)] = null;
}
public override void Process(TagHelperContext context, TagHelperOutput output) {
ArgumentNullException.ThrowIfNull(context);
ArgumentNullException.ThrowIfNull(output);
var items = Items ?? [];
var options = Generator.GenerateGroupsAndOptions(null, items);
output.PostContent.AppendHtml(options);
}
}
Is there any progress or development started in regard to this? I have come across a few requirements that this may help.
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 theasp-items
Razor tag helper.e.g. it would be great to be able to turn
into
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: