Lichte autocomplete-besturingselementen met de HTML5 Datalist

In deze tutorial gaan we diep ingaan op het weinig gebruikte HTML5-element <datalist>. Het kan een lichtgewicht, toegankelijk, cross-browser autocomplete formuliercontrole implementeren die geen JavaScript vereist.

Wat is er mis met <select>?

HTML5 <select>-controles zijn ideaal wanneer u wilt dat de gebruiker uit een kleine reeks opties kiest. Ze zijn minder praktisch wanneer:

  • er veel opties zijn, zoals landen of beroepstitels
  • de gebruiker een eigen optie wil invoeren die niet op de lijst staat

De logische oplossing is een autocomplete-controle. Dit stelt de gebruiker in staat om enkele tekens in te voeren, waardoor de beschikbare opties worden beperkt voor snellere selectie.

<select> springt naar de juiste locatie als u begint met typen, maar dat is niet altijd duidelijk. Het werkt niet op alle apparaten (zoals touchscreens) en het reset binnen een seconde of twee.

Ontwikkelaars grijpen vaak naar een van de vele JavaScript-aangedreven oplossingen, maar een aangepaste autocomplete-controle is niet altijd nodig. Het HTML5 <datalist>-element is lichtgewicht, toegankelijk en heeft geen afhankelijkheden van JavaScript. Je hebt misschien gehoord dat het buggy is of ondersteuning mist. Dat is niet waar in 2021, maar er zijn wel browserinconsistenties en kanttekeningen.

<datalist> Snel Starten

Het selecteren van uw land uit een lijst met meer dan 200 opties is een uitstekende kandidaat voor een autocomplete-besturingselement. Definieer een <datalist> met kind-<option>-elementen voor elk land rechtstreeks in een HTML-pagina:

<datalist id="countrydata">
  <option>Afghanistan</option>
  <option>Åland Islands</option>
  <option>Albania</option>
  <option>Algeria</option>
  <option>American Samoa</option>
  <option>Andorra</option>
  <option>Angola</option>
  <option>Anguilla</option>
  <option>Antarctica</option>
  ...etc...
</datalist>

De id van de datalijst kan vervolgens worden gerefereerd door een list-kenmerk in elk <input>-veld:

<label for="country">country</label>

<input type="text"
  list="countrydata"
  id="country" name="country"
  size="50"
  autocomplete="off" />

Verwarrend genoeg is het het beste om autocomplete="off" in te stellen. Dit zorgt ervoor dat de gebruiker waarden in de <datalist> ziet, maar niet waarden die ze eerder in de browser hebben ingevoerd.

Het resultaat:

Dit is de standaardweergave in Microsoft Edge. Andere toepassingen implementeren soortgelijke functionaliteit, maar het uiterlijk verschilt per platform en browser.

<option> Opties

Het gebruik van de label als tekstkind van een <option> is gebruikelijk:

<datalist id="mylist">
  <option>label one</option>
  <option>label two</option>
  <option>label three</option>
</datalist>

Het gebruik van een value-kenmerk levert identieke resultaten op:

<datalist id="mylist">
  <option value="label one" />
  <option value="label two" />
  <option value="label three" />
</datalist>

Opmerking: de sluitende /> schuine streep is optioneel in HTML5, hoewel het misschien helpen kan bij het voorkomen van coderingfouten.

U kunt ook een waarde instellen volgens een gekozen label met behulp van een van de volgende indelingen.

Optie 1:

<datalist id="mylist">
  <option value="1">label one</option>
  <option value="2">label two</option>
  <option value="3">label three</option>
</datalist>

Optie 2:

<datalist id="mylist">
  <option value="1" label="label one" />
  <option value="2" label="label two" />
  <option value="3" label="label three" />
</datalist>

In beide gevallen wordt het invoerveld ingesteld op 1, 2 of 3 wanneer een geldige optie wordt gekozen, maar de gebruikersinterface verschilt per browser:

  • Chrome toont een lijst met zowel de waarde als de label. Alleen de waarde blijft over zodra een optie is gekozen.
  • Firefox toont een lijst met alleen de label. Het schakelt over naar de waarde zodra een optie is gekozen.
  • Edge toont alleen de waarde.

Het volgende CodePen-voorbeeld toont alle variaties:

Zie de Pen
HTML5 <datalist> autocomplete voorbeelden
door SitePoint (@SitePoint)
op CodePen.

Implementaties zullen zich ontwikkelen, maar voor nu raad ik je af om een waarde en label te gebruiken, aangezien dit waarschijnlijk gebruikers zal verwarren. (Een oplossing wordt hieronder besproken.)

<datalist> Browserondersteuning en fallback

Het <datalist> element wordt goed ondersteund in moderne browsers evenals Internet Explorer 10 en 11:

Er zijn enkele implementatienotities, maar deze zullen de meeste gebruikers niet beïnvloeden. Het ergste dat kan gebeuren is dat een veld terugvalt op een standaard tekstinput.

Als je absoluut IE9 en lager moet ondersteunen, is er een fallback-patroon dat een standaard <select> gebruikt in combinatie met een tekstinput wanneer het <datalist> faalt. Aanpassen van het landvoorbeeld:

<label for="country">country</label>

<datalist id="countrydata">

  <select name="countryselect">
    <option></option>
    <option>Afghanistan</option>
    <option>Åland Islands</option>
    <option>Albania</option>
    <option>Algeria</option>
    <option>American Samoa</option>
    <option>Andorra</option>
    <option>Angola</option>
    <option>Anguilla</option>
    <option>Antarctica</option>
    ...etc...
  </select>

  <label for="country">or other</label>

</datalist>

<input type="text"
  id="country" name="country"
  size="50"
  list="countrydata"
  autocomplete="off" />

Bekijk de Pen
HTML5 <datalist> autocomplete fallback
door SitePoint (@SitePoint)
op CodePen.

In moderne browsers worden de <option> elementen onderdeel van de <datalist> en wordt de “or other” label niet getoond. Het lijkt identiek aan het voorbeeld hierboven, maar een countryselect form waarde wordt ingesteld op een lege string.

In IE9 en lager zijn zowel de (zeer lange) <select> als de tekst invoer velden actief:

Beide waarden konden worden ingevoerd in oude IEs. Uw applicatie moet ofwel:

  • bepalen welke het meest geldig is, of
  • gebruik een kleine JavaScript functie om er een te resetten wanneer de andere wordt gewijzigd

Gebruik van <datalist> op Niet-tekst Controles

Chrome-gebaseerde browsers kunnen ook <datalist> waarden toepassen op:

  1. Een invoer met het type "date". De gebruiker kan kiezen uit een reeks opties gedefinieerd als YYYY-MM-DD waarden, maar gepresenteerd in hun lokale indeling.

  2. Een invoerveld met het type "color". De gebruiker kan kiezen uit een selectie van kleurenopties gedefinieerd als zes-cijferige hexadecimale waarden (drie-cijferige waarden werken niet).

  3. Een invoerveld met het type "range". De schuifknop toont klikmarkeringen, hoewel dit niet beperkt welke waarde ingevoerd kan worden.

Zie de Pen
HTML5 <datalist> op andere invoertypen
door SitePoint (@SitePoint)
op CodePen.

<datalist> CSS Styling

Als je ooit worstelde met het stylen van een <select> box, … je had het gemakkelijk!

Een <input> kan normaal gesproken worden gestyleerd, maar een gekoppelde <datalist> en zijn kind- <option> elementen kunnen niet worden gestyleerd in CSS. De lijstweergave wordt volledig bepaald door het platform en de browser.

I hope this situation improves, but for now, a solution is proposed at MDN which:

  1. overtrekt de standaard browsergedrag
  2. treats de <datalist> effectief als een <div> zodat het kan worden gestyleerd in CSS
  3. replicaties alle autocomplete functionaliteit in JavaScript

I’ve enhanced it further and the code is available on GitHub. To use it, load the script anywhere in your HTML page as an ES6 module. The jsDelivr CDN URL can be used:

<script src="https://cdn.jsdelivr.net/npm/datalist-css/dist/datalist-css.min.js"></script>

Of je kunt het installeren met npm als je een bundler gebruikt:

npm install datalist-css

Je <datalist> elementen moeten de <option>value</option> -indeling gebruiken. Bijvoorbeeld:

<datalist id="mylist">
  <option>label one</option>
  <option>label two</option>
  <option>label three</option>
</datalist>

Opmerking: <option value="value" /> kan niet worden gebruikt, omdat het resulteert in een leeg element dat niet kan worden ge​​stileerd!

CSS kan vervolgens worden toegevoegd om enkele of alle <datalist> en <option> elementen te stylen. Bijvoorbeeld:

datalist {
  position: absolute;
  max-height: 20em;
  border: 0 none;
  overflow-x: hidden;
  overflow-y: auto;
}

datalist option {
  font-size: 0.8em;
  padding: 0.3em 1em;
  background-color: #ccc;
  cursor: pointer;
}

/* actieve optiestijling */
datalist option:hover, datalist option:focus {
  color: #fff;
  background-color: #036;
  outline: 0 none;
}

Voorbeeld:

Zie de Pen
HTML5 <datalist> autocomplete CSS styling
door SitePoint (@SitePoint)
op CodePen.

Styling werkt, maar is het de moeite waard? Ik vermoed van niet …

  • Het opnieuw implementeren van de standaard toetsenbord, muis en touch-besturingselementen van de browser met redelijke toegankelijkheid is moeilijk. Het MDN-voorbeeld ondersteunt geen toetsenbordgebeurtenissen en, hoewel ik probeerde het te verbeteren, zullen er onvermijdelijk problemen zijn op sommige apparaten.
  • Je vertrouwt op 200 regels JavaScript om een CSS-probleem op te lossen. Het minifizeert naar 1,5 kB, maar kan prestatieproblemen introduceren als je veel lange <datalist> elementen op dezelfde pagina vereiste.
  • Als JavaScript een vereiste is, zou het beter zijn om een mooiere, consistentere, beproefde JavaScript-component te gebruiken?

Het controleert terug naar een standaard HTML5 <datalist> zonder opmaak wanneer JavaScript faalt, maar dat is een kleine voordeel.

Het maken van een Ajax-gebaseerde <datalist>

Stel dat je ontwerper het ermee eens is om te accepteren dat er verschillen zijn in browseropmaak, dan is het mogelijk om de standaardfunctionaliteit van <datalist> te verbeteren met behulp van JavaScript. Bijvoorbeeld:

  1. Optionele validatie implementeren die alleen een bekende waarde in de <datalist> toelaat.
  2. Stel <option>-elementen in op basis van gegevens die worden geretourneerd door Ajax-oproepen naar zoek-API’s.
  3. Stel andere veldwaarden in wanneer een optie wordt gekozen. Bijvoorbeeld, het selecteren van “Verenigde Staten van Amerika” zet “US” in een verborgen input.

De code moet voornamelijk <option>-elementen herdefiniëren, hoewel er verschillende programmeeroverwegingen zijn:

  • Een Ajax-API-aanvraag mag alleen plaatsvinden nadat een minimumaantal tekens is ingevoerd.
  • Toetsaanslagen moeten gedempt worden. Dat wil zeggen, een Ajax-oproep wordt alleen geactiveerd nadat de gebruiker ten minste een halve seconde heeft stilgezeten.
  • Zoekresultaten moeten worden gecacheerd, zodat het niet nodig is om identieke oproepen te herhalen of te parseren.
  • Onnodige query’s moeten worden vermeden. Bijvoorbeeld, het invoeren van “un” retourneert 12 landen. Er is geen behoefte om verdere Ajax-oproepen te doen voor “unit” of “united” omdat alle resulterende opties in de oorspronkelijke 12 resultaten zijn opgenomen.

I’ve created a standard Web Component for this, and the code is available on GitHub. The CodePen example below allows you to select a valid country after entering at least two characters. A music artist autocomplete then returns artists who originated in that country with names matching the search string:

Zie de Pen
HTML5 <datalist> met Ajax autocomplete
door SitePoint (@SitePoint)
op CodePen.

Om het in uw eigen toepassing te gebruiken, laad het script overal op uw HTML-pagina als een ES6-module. De jsDelivr CDN URL kan worden gebruikt:

<script src="https://cdn.jsdelivr.net/npm/datalist-ajax/dist/datalist-ajax.min.js"></script>

Of u kunt het installeren met npm als u een bundler gebruikt:

npm install datalist-ajax

Maak een <auto-complete> element met een kind <input> om te gebruiken als de gegevensinvoerveld. Bijvoorbeeld, de landzoek gebruikt dit:

<label for="country">country lookup:</label>

<auto-complete
  api="https://restcountries.eu/rest/v2/name/${country}?fields=name;alpha2Code;region"
  resultname="name"
  querymin="2"
  optionmax="50"
  valid="please select a valid country"
>
  <input type="text" id="country" name="country" size="50" required />
</auto-complete>

<auto-complete> element attributen:

attribute description
api the REST API URL (required)
resultdata the name of the property containing a result array of objects in the returned API JSON (not required if only results are returned)
resultname the name of the property in each result object which matches the search input and is used for datalist <option> elements (required)
querymin the minimum number of characters to enter before a search is triggered (default: 1)
inputdelay the minimum time to wait in milliseconds between keypresses before a search occurs (default debounce: 300)
optionmax the maximum number of autocomplete options to show (default: 20)
valid if set, this error message is shown when an invalid value is selected

De REST-URL moet ten minste één ${id} identificatie bevatten, die wordt vervangen door de waarde die is ingesteld in de <input> met die id. In het bovenstaande voorbeeld verwijst ${country} in de api URL naar de waarde in het kind-<input>, dat een id heeft van "country". De URL zal normaal gesproken de kind-input gebruiken, maar elke andere velden op de pagina kunnen worden geraadpleegd.

De restcountries.eu API retourneert een enkel object of een array van objecten met landgegevens. Bijvoorbeeld:

[
  {
    "name": "Cyprus",
    "alpha2Code": "CY",
    "region": "Europe"
  },
  {
    "name": "Sao Tome and Principe",
    "alpha2Code": "ST",
    "region": "Africa"
  },
  {
    "name": "Andorra",
    "alpha2Code": "AD",
    "region": "Europe"
  }
]

Het resultdata attribuut hoeft niet ingesteld te worden omdat dit de enige teruggegeven gegevens zijn (er is geen wrapper-object). Het resultname attribuut moet worden ingesteld op "name" omdat die eigenschap wordt gebruikt om datalist <option> elementen te vullen.

Andere velden kunnen automatisch worden ingevuld wanneer een optie wordt gekozen. De volgende inputs ontvangen de "alpha2Code" en "region" eigenschapsgegevens omdat een data-autofill attribuut is ingesteld:

<input data-autofill="alpha2Code" type="text" id="countrycode" name="countrycode" readonly />

<input data-autofill="region" type="text" id="region" name="region" readonly />

Hoe datalist-ajax werkt

Je kunt deze sectie overslaan als je liever niet 230 regels code leest en de magie in leven houdt!

Het codefragment begint met het aanmaken van een nieuwe <datalist> binnen de <auto-complete>, die vervolgens wordt gekoppeld aan het kind <input> via een list attribuut. Een input event handler controleert het <input> en roept de runQuery() functie aan wanneer een minimum aantal karakters is ingevoerd en de gebruiker niet meer aan het typen is.

runQuery() bouwt de API URL aan de hand van gegevens in het formulier en maakt een Ajax oproep met behulp van de Fetch API. De teruggekeerde JSON wordt geëvalueerd, waarna een herbruikbare DOM-fragment met <option> elementen wordt opgebouwd en in een cache wordt geplaatst.

A datalistUpdate() function is called, which updates the <datalist> with the appropriate cached DOM fragment. Further calls to runQuery() avoid Ajax calls if a query has already been cached or a previous query can be used.

A change event handler also monitors the <input>, which is triggered when focus is moved from the field and the value has been modified. The function checks that the value matches a known option and, if necessary, uses the Constraint Validation API to show the error message provided in the valid attribute.

Als een geldige optie is gekozen, vult de change handler functie alle velden met overeenkomende data-autofill attributen. Een referentie naar de auto-fill velden wordt bewaard zodat deze kunnen worden gereset als er vervolgens een ongeldige optie wordt ingevoerd.

Het is vermeldenswaard dat de shadow DOM niet wordt gebruikt. Dit zorgt ervoor dat de auto-complete <input> (en <datalist>) elementen door CSS kunnen worden gestileerd en indien nodig door andere scripts kunnen worden geopend.

Dunkin’ <datalist>

De HTML5 <datalist> heeft beperkingen, maar is ideaal als je een eenvoudige framework-onafhankelijke auto-complete veld nodig hebt. Het ontbreken van CSS-ondersteuning is jammer, maar browserleveranciers kunnen dat uitzicht uiteindelijk wel aanpassen.

Elk van de code en voorbeelden die in deze tutorial worden getoond, kan worden overgenomen voor je eigen projecten.

FAQs over lichtgewicht autocomplete-besturingselementen met de HTML5 Datalist

Wat is het HTML5 datalist-element en hoe werkt het?

Het HTML5 datalist-element is een vooraf gedefinieerde lijst met opties voor een invoer-element. Het biedt een “autocomplete” functie op formuliergegevens. Het datalist-element gebruikt het id-kenmerk om het te associëren met een specifiek invoerelement. Het invoerelement gebruikt het list-kenmerk om het datalist te identificeren. Binnen het datalist kunt u option-elementen definiëren die de beschikbare opties voor het invoerveld vertegenwoordigen.

Hoe kan ik het HTML5 datalist gebruiken voor autocomplete?

Om het HTML5 datalist te gebruiken voor autocomplete, moet u het datalist associëren met een invoerveld. Dit wordt gedaan door het list-kenmerk toe te voegen aan het invoerveld en de waarde ervan in te stellen op de id van het datalist. De browser zal dan autocomplete-suggesties aanbieden op basis van de invoer van de gebruiker en de gedefinieerde opties in het datalist.

Kan ik het HTML5 datalist-element in alle browsers gebruiken?

Het HTML5 datalist-element wordt ondersteund in de meeste moderne browsers, waaronder Chrome, Firefox, Safari en Edge. Er wordt echter geen ondersteuning geboden in Internet Explorer 9 en eerdere versies. U kunt de huidige browsercompatibiliteit op websites zoals Can I Use controleren.

Hoe kan ik de HTML5 datalist-opties stylen?

Helaas zijn de stylingsmogelijkheden voor het HTML5 datalist-element beperkt. Het uiterlijk van de dropdown-lijst wordt beheerst door de browser en kan niet gemakkelijk worden aangepast met CSS. U kunt echter het invoerveld associëren met het datalist stylen.

Kan ik meerdere datalists gebruiken voor een enkel invoerveld?

Nee, je kunt niet meerdere datalijsten koppelen aan één invoerveld. De list-attribuut van het invoerveld kan maar één id aannemen, wat overeenkomt met één datalijst. Als je meerdere sets opties wilt bieden, moet je misschien JavaScript gebruiken om de opties dynamisch te wijzigen op basis van gebruikersinput.

Kan ik de HTML5 datalijst gebruiken met andere invoertypen?

Ja, de HTML5 datalijst kan worden gebruikt met verschillende invoertypen, waaronder tekst, zoeken, url, tel, e-mail, datum, maand, week, tijd, datetime-local, nummer, bereik en kleur. De autocomplete-functie werkt echter misschien niet zoals verwacht met sommige invoertypen zoals bereik of kleur.

Kan ik de HTML5 datalijst gebruiken met een select-element?

Nee, de HTML5 datalijst kan niet worden gebruikt met een select-element. De datalijst is ontworpen om autocomplete-suggesties te bieden voor een invoerveld, terwijl het select-element een dropdown-lijst met opties biedt. Als je een dropdown-lijst nodig hebt, moet je het select-element gebruiken.

Kan ik JavaScript gebruiken met de HTML5 datalijst?

Ja, je kunt JavaScript gebruiken met de HTML5 datalijst om opties dynamisch toe te voegen, te verwijderen of te wijzigen. Houd er echter rekening mee dat de datalijst geen gebeurtenissen ondersteunt zoals onchange of onclick op zijn opties. Je moet de gebeurtenislisterners toevoegen aan het gekoppelde invoerveld.

Kan ik de HTML5 datalijst gebruiken voor een zoekveld?

Ja, de HTML5 datalijst kan een uitstekende keuze zijn voor een zoekveld. Het kan autocomplete-suggesties bieden op basis van de invoer van de gebruiker, wat de gebruikerservaring kan verbeteren. Je moet echter de datalijst handmatig vullen met de mogelijke zoektermen.

Kan ik de HTML5 datalist gebruiken met een textarea?

Nee, de HTML5 datalist kan niet worden gebruikt met een textarea. De datalist is ontworpen om autocomplete suggesties te bieden voor een invoerveld, niet voor een textarea. Als u autocomplete functionaliteit nodig heeft voor een textarea, moet u misschien een JavaScript bibliotheek gebruiken of uw eigen oplossing bouwen.

Source:
https://www.sitepoint.com/html5-datalist-autocomplete/