Vai al contenuto principale

Autocompletamento

Elementi e stili per la creazione di input con autocompletamento.

Esempio di autocompletamento

Il completamento automatico è un componente che aiuta gli utenti a scegliere le risposte da un elenco fornito. Per la creazione del componente, è stato utilizzato il plugin Accessible autocomplete.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="form-group">
  <label for="accessibleAutocomplete">Regione</label>
  <div id="accessibleAutocompleteWrapper" class="autocomplete-wrapper"></div>
</div>
<script>
  document.addEventListener('DOMContentLoaded', function () {
    const italianRegions = ["Abruzzo","Basilicata","Calabria","Campania","Emilia Romagna","Friuli Venezia Giulia","Lazio","Liguria","Lombardia","Marche","Molise","Piemonte","Puglia","Sardegna","Sicilia","Toscana","Trentino Alto Adige","Umbria","Valle d’Aosta","Veneto"];
    const selectElement = document.querySelector('#accessibleAutocompleteWrapper');
    const selectAutocomplete = new bootstrap.SelectAutocomplete(selectElement, {
      id: 'accessibleAutocomplete',
      name: 'regioni',
      source: italianRegions
    });
  })
</script>

Cambiare i valori dinamicamente

In questo esempio viene mostrato come popolare il componente con dati che cambiano a fronte di un altro input, ad esempio il valore di un altro elemento di un form (come una select nell’esempio che segue). Per far fronte a questa esigenza è sufficiente passare come opzione source una funzione per filtrare i dati e popolare il componente (Tutte le opzioni disponibili del componente).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<div class="row">
  <div class="col-12">
    <div class="form-group">
      <div class="select-wrapper">
        <label for="category">Categoria alimento</label>
        <select id="category" name="category">
          <option value="frutta" selected>Frutta</option>
          <option value="verdura">Verdura</option>
        </select>
      </div>
    </div>
  </div>
  <div class="col-12">
    <div class="form-group">
      <label for="productAutocomplete">Alimento</label>
      <div id="productAutocompleteWrapper" class="autocomplete-wrapper"></div>
    </div>
  </div>
  <script>
    const form_data = {
      'frutta' : [
        'Mela',
        'Pera',
        'Melone',
        'Banana',
      ],
      'verdura' : [
        'Carota',
        'Zucchina',
        'Melanzana',
        'Carciofo',
      ],
    }
    document.addEventListener('DOMContentLoaded', function () {
      const categorySelect = document.getElementById("category");
      const selectWrapperElement = document.getElementById("productAutocompleteWrapper");
      const selectAutocomplete = new bootstrap.SelectAutocomplete(selectWrapperElement, {
        id: 'productAutocomplete',
        name: 'prodotto',
        source: (query, populateResults) => {
          const results = form_data[categorySelect.value]
          const filteredResults = results.filter(
            result => result.toLowerCase() .indexOf(query.toLowerCase()) !== -1
          )
          populateResults(filteredResults)
        }
      });
      // Facoltativo: se si vuole cancellare l'elemento al cambio del filtro
      categorySelect.addEventListener('change', (event) => {
        document.getElementById("productAutocomplete").value = '';
      });
    })
  </script>
</div>

Esempio Regioni e Comuni

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<div class="row">
  <div class="col-12">
    <div class="form-group">
      <div class="select-wrapper">
        <label for="regione">Regione</label>
        <select id="regione" name="regione">
          
          <option value="Abruzzo">Abruzzo</option>
          
          <option value="Basilicata">Basilicata</option>
          
          <option value="Calabria">Calabria</option>
          
          <option value="Campania">Campania</option>
          
          <option value="Emilia Romagna">Emilia Romagna</option>
          
          <option value="Friuli Venezia Giulia">Friuli Venezia Giulia</option>
          
          <option value="Lazio">Lazio</option>
          
          <option value="Liguria">Liguria</option>
          
          <option value="Lombardia">Lombardia</option>
          
          <option value="Marche">Marche</option>
          
          <option value="Molise">Molise</option>
          
          <option value="Piemonte">Piemonte</option>
          
          <option value="Puglia">Puglia</option>
          
          <option value="Sardegna">Sardegna</option>
          
          <option value="Sicilia">Sicilia</option>
          
          <option value="Toscana">Toscana</option>
          
          <option value="Trentino Alto Adige">Trentino Alto Adige</option>
          
          <option value="Umbria">Umbria</option>
          
          <option value="Valle d’Aosta">Valle d’Aosta</option>
          
          <option value="Veneto">Veneto</option>
          
        </select>
      </div>
    </div>
  </div>
  <div class="col-12">
    <div class="form-group">
      <label for="comuniAutocomplete">Comune</label>
      <div id="comuniAutocompleteWrapper" class="autocomplete-wrapper"></div>
    </div>
  </div>
  <script>
    document.addEventListener('DOMContentLoaded', async function () {
      const italianRegions = ["Abruzzo","Basilicata","Calabria","Campania","Emilia Romagna","Friuli Venezia Giulia","Lazio","Liguria","Lombardia","Marche","Molise","Piemonte","Puglia","Sardegna","Sicilia","Toscana","Trentino Alto Adige","Umbria","Valle d’Aosta","Veneto"];
      const data = {}
      italianRegions.forEach(region => { data[region] = [] })
      const comuniJson = await (await fetch('/docs/esempi/form/comuni.json')).json();
      comuniJson.forEach(comune => data[comune.regione].push(comune.comune))
      const regioniSelect = document.getElementById("regione");
      const selectWrapperElement = document.getElementById("comuniAutocompleteWrapper");
      const selectAutocomplete = new bootstrap.SelectAutocomplete(selectWrapperElement, {
        id: 'comuniAutocomplete',
        name: 'comuni',
        source: (query, populateResults) => {
          const results = data[regioniSelect.value]
          const filteredResults = results.filter(
            result => result.toLowerCase() .indexOf(query.toLowerCase()) !== -1
          )          
          populateResults(filteredResults)
        }
      });
      regioniSelect.addEventListener('change', (event) => {
        document.getElementById("comuniAutocomplete").value = '';
      });
    })
  </script>
</div>

Validazione

Per la validazione del campo con autocompletamento, si consiglia di utilizzare il plugin Just Validate come da guida. È possibile testare la validazione del campo con autocompletamento sulla pagina di esempio validazione.

Quando l’utente seleziona un valore dalla tendinda di Autocomplete occorre richiamare nuovamente la funzione di validazione. Questa chiamata può essere effettuata all’interno del metodo onConfirm che viene passato in configurazione e verrà chiamata ogni volta che l’utente seleziona un opzione.

Ad esempio con JustValidate occorrerà istanziare il componente in questo modo

1
2
3
4
5
6
7
const selectAutocomplete = new SelectAutocomplete(selectAutocompleteWrapper, {
  source: myData,
  id: 'idAutocomplete',
  onConfirm: () => {
    validate.revalidateField('#idAutocomplete')
  }
});

Il campo verrà validato così anche nel caso in cui l’utente seleziona un’opzione. Nel caso in cui è stato impostato che JustValidate validi il form solo dopo la submit occorre controllare il suo stato

1
2
3
4
5
  onConfirm: () => {
    if (!validate.isSubmitted && !validate.validateBeforeSubmitting)
      return
    validate.revalidateField('#idAutocomplete')
  }

Nell’esempio seguente si può provare questo comportamento (si noti che tra le configurazioni è stato passato anche minLength: 3, vista la grande mole di dati questa opzione impedirà la visualizzazione dei suggerimenti se vengono digitati meno di 3 caratteri)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<div>
  <form id="justValidate">
    <div class="row">
      <div class="col-12">
        <div class="form-group">
          <label for="comuneJVAutocomplete">Comune di residenza</label>
          <div id="comuneJVAutocompleteWrapper" class="autocomplete-wrapper"></div>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="col-12">
        <button class="btn btn-primary mt-3" type="submit" id="submitform">Invia form</button>
      </div>
    </div>
  </form>
  <script>
    document.addEventListener('DOMContentLoaded', async function () {
      const validate = new bootstrap.FormValidate('#justValidate', {
        errorFieldCssClass: 'is-invalid',
        errorLabelCssClass: 'form-feedback',
        errorLabelStyle: '',
        focusInvalidField: false,
      })
      const comuniJson = await (await fetch('/docs/esempi/form/comuni.json')).json();
      const comuni = comuniJson.map(comune => comune.comune)
      const selectAutocompleteWrapper = document.querySelector('#comuneJVAutocompleteWrapper');
      const selectAutocomplete = new bootstrap.SelectAutocomplete(selectAutocompleteWrapper, {
        source: comuni,
        id: 'comuneJVAutocomplete',
        name: 'comuni',
        minLength: 3,
        onConfirm: () => {
          if (!validate.isSubmitted && !validate.validateBeforeSubmitting)
            return
          validate.revalidateField('#comuneJVAutocomplete')
        }
      });
      validate
        .addField('#comuneJVAutocomplete', [
          {
            rule: 'required',
            errorMessage: 'Questo campo è richiesto',
          },
          {
            validator: (value) => {
              return comuni.includes(value);
            },
            errorMessage: 'Scegli una città valida',
          },
        ])
        .onSuccess((event) => {
          // Inserire qua l'azione nel caso di input valido, ad es.
          // document.forms['justValidate'].submit()
        })
      })
  </script>
</div>

Attivazione tramite codice

È possibile abilitare l’autocomplete manualmente utilizzando l’oggetto SelectAutocomplete.

1
2
3
4
import { SelectAutocomplete } from 'bootstrap-italia';

const autocompleteWrapperElement = document.querySelector('#wrapper-autocomplete');
const autocomplete = new SelectAutocomplete(autocompleteWrapperElement, options);

Opzioni

1
2
3
4
5
6
7
8
9
10
11
import { SelectAutocomplete } from 'bootstrap-italia';

const selectAutocompleteWrapper = document.querySelector('#accessibleAutocompleteWrapper');
const selectAutocomplete = new SelectAutocomplete(selectAutocompleteWrapper, {
  source: ['Option 1', 'Option 2', 'Option 3'],
  id: 'accessibleAutocomplete',
  minLength: 3,
  onConfirm: (selectedElement) => {
    console.log(selectedElement);
  }
});
Nome Tipo Predefinito Descrizione
source Array | Function - Sorgente di dati dell'autocomplete. Se "source è una funzione, gli argomenti sono: (query: string, populateResults: Funzione): "query" è ciò che viene digitato nel campo di input, che richiamerà la funzione "populateResults" in modo sincrono con l'array di risultati da visualizzare nel menu (esempi sopra).
id string - Id dell'elemento input che verrà generato dall' Autocomplete.
name string input-autocomplete Nome del campo di input di completamento automatico, da utilizzare con un form padre.
minLength number 0 Questa opzione impedisce la visualizzazione dei suggerimenti se vengono digitati meno di N caratteri.
defaultValue string - Valore di default inserito nell'input.
required boolean false Il campo di input verrà renderizzato con un attributo obbligatorio.
onConfirm function {} Questa funzione viene chiamata quando l'utente conferma un'opzione, con l'opzione che ha confermato come argomento (si vedano gli esempi precedenti).

Metodi

Metodo Descrizione
getInstance Metodo statico che consente di ottenere l'istanza di avviso associata a un elemento DOM, è possibile utilizzarlo in questo modo: SelectAutocomplete.getInstance(domElement).
getOrCreateInstance Metodo statico che restituisce un'istanza di avviso associata a un elemento DOM o ne crea una nuova nel caso in cui non fosse stata inizializzata. Puoi utilizzarla in questo modo: SelectAutocomplete.getOrCreateInstance(element).
dispose Rimuove la funzionalità SelectAutocomplete.

Internazionalizzazione (i18n)

Il componente è internazionalizzabile tramite alcuni parametri della configurazione. La configurazione per Bootstrap Italia è stata settata in italiano. Per maggiori dettagli sulle stringhe che possono essere passate al componente fare riferimento alla guida ufficiale.

Breaking change

Nuova modalità di utilizzo del componente Autocomplete via codice.