multi choice dropdown from database with hundreds of entries

I am creating a wix website where I have 2 types of memberships: clients A and companies B. The idea of it is that B sign up and post their services on the website and A sign up and can look up for Bs in different locations, and can contact the B and start a chat with them on the platform.

How can I create a dropdown with multiple selection where B can introduce the (single or multiple) locations where they work (we have database with major cities) - this should be autofill.

I tried following tutorials and the dropdown just won’t work.

Please heeeeelp I am in panic mode!

Hi Brandstorm X I just answered to you with another post. It’s waiting for approval :+1:

Let’s try this for now. It works with keyboard, type a letter and then use arrow keys to choose a voic and then press Enter. But It doesn’t work with mouse :frowning:
@yisrael-wix

https://mauroavino.wixsite.com/testquery/autocomplete3

Ok so I’will post here the code, it’s really simple use it !
It was developed by @yisrael-wix on a my simple idea and of David - skeptisch.net .
Next I tuned the code in order to make it modular. You ca use it for one or more dropdown menu.

  1. So you need in the principal Page of one (or more) text_input and a repeater (to realize the menu). In the repeated elements of repeater you need: one text box and one container box (to realize the background of the field).

  2. In the page you have to write a really simple page routine to set the variables and to invoke the main routine in /public/menu_input.js

  3. in /pubblic the main routine menu_input.js

  4. a collection in the database, OR set an array static data

PAGE ROUTINE

import {menu_input} from 'public/menu_input.js'
$w.onReady( function () {

/****************************************/
/* set repeater (liste dinamiche)       */
/****************************************/

let input1		=$w('#input1')
let repeater1	=$w('#repeater1')
// le seguenti voci non usano $w() perchè andranno richiamate con $item() in menu_input.js
let container1	=   '#container1'
let voce1		=   '#text1'
let sfondo1		=   '#box1'


/**********************************/
/* set the input collections      */
/**********************************/

// crea i riferimenti della collezione nel dbase
let collezione1	=	'Producers'
let campo1		=	'nominativo'


/********************************************************/
/* invoke the same function for the different repeaters */
/********************************************************/

menu_input (input1,repeater1,container1,voce1,sfondo1,collezione1,campo1)


});

MAIN ROUTINE /public/menu_input.js

 import wixData from 'wix-data';


/********************************************************/
/******* FUNZIONE MENU SEARCH & NAVIGATOR ARRAY      ****/
/********************************************************/
// This project was inspired by a recent forum discussion, Highlight an item Repeater - autocomplete menu,
// between amazing users: Mauro Vento Avyno and David - skeptisch.net.
// and the principal contributor the Master Yisrael(Wix)

// Di seguito la funzione 'menu_input', richiamata dalla Home-page, è destinata a popolare i repeater dei menu a tendina con le voci ricavate dalla collezione
// I primi cinque parametri costituiscono la struttura del menu a tendina
// input     == la casella di input testo
// repeater  == è il nome del repeater usato per costruire il menu (liste dinamiche)
// container == è il nome del riquadro contenitore 
// voce      == è la singola voce del menu a tendina
// sfondo    == il nome della box che da sfondo alla voce

// collezione== il nome del database || oppure una [matrice] di valori sui quali effettuare la ricerca
// campo     == il nome del campo del database sul quale si effettua la ricerca (ex. 'nominativo')   

export async function menu_input (input,repeater,container,voce,sfondo,collezione, campo) {

let options={suppressAuth:true,suppressHokks:true}
const HL_COLOR = "rgba(190,190,250)";
const REG_COLOR = "rgba(222,222,222)";
let listSize;
let currIndex = -1;

$w(sfondo).style.backgroundColor = REG_COLOR;
repeater.collapse()

//*********************************************************/
/*   CREA 'ArraY' come l'array di elementi (_id, campo) con il quale lavorare   */
//*********************************************************/

// verifica se 'collezione' contiene il nome di un dbase e se questo esiste 
if (typeof(collezione)==="string" && wixData.query(collezione)) {
	console.log("Esiste la collezione nel database: ",collezione)
// interroga la collezione e crea l'elemento 'ArraY'	
	await wixData.query(collezione)
	.find()
	.then( (res) => { ArraY = res.items})
}
else if
// oppure se 'collezione' è in effetti esso stesso un Array semplice, cioè se un elemento di esso è una stringa invece di un oggetto, 
// in tal caso crea 'ArraY' formato da oggetti del tipo (_id, valore)
(Array.isArray(collezione) && typeof(collezione[0])==="string") { 
var ArraY=[], i=0, ARRAY=[];
// predispone 'ArraY'
collezione.forEach( (el) => { ArraY.push( { [campo]:el,"_id":String(i) }); ++i })
console.log("'collezione' è un array semplice di valori",collezione)
}
// oppure se 'collezione' è un Array i cui elementi sono oggetti 
else if ( Array.isArray(collezione) && typeof(collezione[0])==="object" )  {
console.log("È un oggetto: ", collezione)
var ArraY = collezione, i=0, ARRAY=[];	
}
else {console.log("'collezione' non è ne un riferimento ad un database, ne un array semplice, ne una collezione di record/items")}


/*********************************************************/
/* popola le voci del menu
/* in pratica i dati ricavati                */
/*********************************************************/

// carica l'array nel repeater
repeater.data=ArraY;

// appena repeater.data sarà stato caricato
// gli $item saranno pronti, sono i singoli elementi ripetuti del repeater,
// gli itemData saranno i dati caricati dall'array
// non ci resta che assegnare i singoli valori (ex. itemData.nominativo --> $w(#text1).text )
repeater.onItemReady( ($item, itemData, index) => {

	$item(voce).text = itemData[campo];
	console.log('ciao');

//*****************************************************/
// verifica il clik del MOUSE sull'elemento ripetuto  */
//*****************************************************/
	$item(container).onClick (()=>{
		console.log('hai cliccato',itemData[campo]);
		input.value=itemData[campo];
		repeater.collapse() 
	})


}) 




//*********************************************************/
//**** CONTROLLO DELL'INPUT DA TASTIERA E DEL REPEATER    */
//*********************************************************/

// aggiunge un *gestore di eventi tramite codice* alla casella input 
// chiude il menu al passaggio del mouse
input.onMouseIn(() => {repeater.collapse()})

// chiude il menu all'uscita da input
input.onBlur( () => {repeater.collapse()})


// controlla ogni singolo input da tastiera e popola il menu	
input.onKeyPress((event) => {
		console.log(event.key)
		setTimeout(() => {
			if (input.value.length === 0) {
			
			currIndex = -1;
			repeater.collapse()
					
			} else {

				switch (event.key) {
				
				case "Tab":
					repeater.collapse()
					break;		
				

// Per ogni pressione del tasto freccia verrà incrementato di 1 il contatore currIndex
// Altrettanto partirà un ciclo con forEachItem(index) tra tutte le voci presenti nel repeater
// Agendo sul componente 'sfondo' la voce corrispondente al currIndex si illuminerà di un colore diverso
//*****        purtoppo  .style.backgroundColor NON agisce sull'elemento container            ******/  
				case "ArrowRight":
				case "ArrowDown":
					if (currIndex < listSize - 1) {
						currIndex += 1;
						repeater.forEachItem(($item, itemData, index) => {
						
						if (index === currIndex) {
						$item(sfondo).style.backgroundColor = HL_COLOR;
						} else {
						$item(sfondo).style.backgroundColor = REG_COLOR;
						}
						});
					}
					else { currIndex = -1}
					break;

				
				case "ArrowLeft":
				case "ArrowUp":
					if (currIndex > 0) {
						currIndex -= 1;
						repeater.forEachItem(($item, itemData, index) => {
						
						if (index === currIndex) {
						$item(sfondo).style.backgroundColor = HL_COLOR;
						} else {
						$item(sfondo).style.backgroundColor = REG_COLOR;
						}
						});
					}
					else { currIndex = listSize}
					break;
				
								
				case "Escape":
					//input.value = '';
					//currIndex = -1;
					repeater.collapse()
					break;
				
				// 
				case "Enter":
					try {
						console.log(repeater.data)
						if (currIndex === -1) {input.value = repeater.data[0][campo]}
						else {input.value = repeater.data[currIndex][campo];}
						console.log("IL dato esiste")
						repeater.collapse()
					} catch (err) { console.log("Il dato non esiste", err)}
					break;
					
// popola il repeater con i risultati della ricerca
				default:
					ARRAY=[];
					currIndex = -1;
// passa in rassegna gli elementi 'valore' dell'Array
// e seleziona quelli contenenti una parte di stringa da 'input'
					ArraY.forEach( (el) => { if( el[campo].toLowerCase().includes(input.value.toLowerCase()) ) {ARRAY.push(el) }  } )
					console.log("ARRAY = ",ARRAY)

					repeater.data = [];
					repeater.data = ARRAY;
					listSize = ARRAY.length;
					repeater.expand();
					
					break;
				}
			}
	
		}, 50) // chiude SetTimeOut

}); // chiude onKeyPress event




}

Unfortunely $item(container).onClick (()=>{… doesn’t work on PC, only on Mobile!

BUT if you replace it with for example with $item(container).onMouseIn works very well. I Believe it’s an API bug !

Anyway this is an image of the Page, let me know if it works ! Ciao :wave: