Adding an autocomplete textbox using JavaScript

Overview

Thanks to jQuery UI, you can use a combination of JavaScript and C# code to set a textbox with an autocomplete filter.

Autocomplete%20result

Example

You can download the TEXTBOX_AUTOCOMPLETE process as an example.

Based on @qdurand post you can download the AUTOCOMPLETE_PAGE_METHODS process example.

How it works

To create the autocomplete filter, we used jQuery UI’s Autocomplete widget.

To get the filtered list content, we execute a SQL query in the code-behind. The results will be formatted in JavaScript array format and set in a hidden field (REQUEST_USER_LIST)

private void GetUser()
{
    string queryString = "SELECT CONCAT(LASTNAME,' ',FIRSTNAME) as name, USERNAME FROM USERS";
    string queryJs = "[";
    using(System.Data.SqlClient.SqlConnection sqlConnection = new System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings["MainDbSource"].ToString()))
    {
        System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(queryString, sqlConnection);
        sqlConnection.Open();
            using (System.Data.SqlClient.SqlDataReader reader = command.ExecuteReader())
            {
                if (reader.HasRows)
                {
                    while (reader.Read())
                    {
                        queryJs = queryJs + "{ value :'" + reader[0].ToString() +
                            "', login :'" + reader[1].ToString() + "'},";
                    }
                    queryJs.Substring(queryJs.Length-1);
                }
                queryJs += "]";
            }
        sqlConnection.Close();
        }

    REQUEST_USER_LIST.Text = queryJs;
}

To add the JavaScript code, go to the Web References tab in the Form configuration panel.

Find%20js%20code

Code example

This example gets the value of the hidden REQUEST_USER_LIST field, and transforms this into a JavaScript array.

if(typeof $selectedObject === "undefined") {
    $(function() {

    $("#REQUEST_ROW_USER_LIST").hide()
       var array = eval($("#REQUEST_USER_LIST").val());

        $('#REQUEST_FILTER').autocomplete({
            source : array,

             select : function(event, ui){ // When a selection is done
                $('#REQUEST_LOGIN').val(ui.item.login); // we add login in the specific field
            }
        });
    })
}
1 Like

Bonjour,
Lorsque la liste retournée par la requête SQL est trop longue a générer puis a être traitée par le javascript, comment faire pour que cette liste ne soit créée (ou requête lancée) qu’après avoir saisi 3 caractères dans le champs Research et non tout au début ?

Bonjour @pclainchard,

Vous pouvez essayer cela:

$('#REQUEST_FILTER').autocomplete({
            source : array,
            minLength: 3,
             select : function(event, ui){ // When a selection is done
                $('#REQUEST_LOGIN').val(ui.item.login); // we add login in the specific field
            }
        }); 

Voici un article concernant minLength dans JQuery:
https://api.jqueryui.com/autocomplete/#option-minLength

Cordialement,
Eddy.

Bonjour Eddy

Merci pour la réponse mais le problème ne se situe pas (que) à ce niveau là.

Dans l’exemple ci-dessus, la requête SQL est lancée dès l’ouverture du formulaire et met environ 15" a s’exécuter (environ 10K users), la liste contenue dans #REQUEST_USER_LIST est OK mais le javascript est incapable de traiter une telle liste.

Mon idée était de ne déclencher la requête SQL modifiée que lorsque le champ #REQUEST_FILTER contient 3 caractères dynamiquement sans avoir a cliquer sur un bouton par ex.

string queryString = “SELECT CONCAT(LASTNAME,’ ',FIRSTNAME) as name, LASTNAME, FIRSTNAME, USERNAME FROM USERS WHERE LASTNAME LIKE '” + REQUEST_FILTER.Text + “%’”;

Cordialement,
Pierre

Bonjour @pclainchard ,

Une possibilité pourrait être d’utiliser le mode Ajax et de faire pointer la source du composant autocomplete vers une méthode du code-behind.

>> Code behind

Activer les Web methods depuis la méthode Page_Load :

protected void Page_Load(object sender, EventArgs e)
{
    base.Page_Load(sender, e);
    ScriptManager1.EnablePageMethods = true;
}

Créer la méthode permettant de récupérer les utilisateurs en se connectant à la base SQL et qui prend comme paramètre une chaîne représentant les premières lettres entrées par l’utilisateur pour sa recherche :

public static string GetUsers(string indice)
{
	var users = new List<string>();
	
	string queryString = "SELECT CONCAT(LASTNAME,' ',FIRSTNAME) as name, USERNAME FROM USERS WHERE LASTNAME LIKE '%" + indice + "%' OR FIRSTNAME LIKE '%" + indice + "%'";
	
 	using(System.Data.SqlClient.SqlConnection sqlConnection = new System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings["MainDbSource"].ToString()))
    {
		System.Data.SqlClient.SqlCommand command = new System.Data.SqlClient.SqlCommand(queryString, sqlConnection);
		sqlConnection.Open();
		
		using (System.Data.SqlClient.SqlDataReader reader = command.ExecuteReader())
		{
			if(reader.HasRows)
			{
				while (reader.Read())
				{
					users.Add("{ value : '" + reader[0].ToString() + "', login : '" + reader[1].ToString() + "' }");
				}
			}
		}
		
		sqlConnection.Close();
	}
	
	return "[" + String.Join(", ", users) + "]";
}

C’est la requête SQL qui s’occupe de filtrer les résultats avec les opérations LIKE.

Ajouter l’attribut System.Web.Services.WebMethod comme entête de la méthode :

[System.Web.Services.WebMethod]
public static string GetUsers(string indice)

>> Script de l’onglet "Références Web"

Utiliser la méthode créée dans le code behind via l’objet PageMethods dans la partie source du composant autocomplete :

$("#REQUEST_FILTER").autocomplete({
	source: function(request, response){
		PageMethods.GetUsers(request.term, succes, erreur);
		function succes(resultat)
		{
			response(eval(resultat));
		}
		function erreur(resultat)
		{
			console.log("Erreur lors de la récupération des utilisateurs : " + resultat);
		}
	},
	minLength: 3,
	select: function(event, ui){
		$('#REQUEST_LOGIN').val(ui.item.login);
	}
});

La propriété term de la variable request contient la saisie de l’utilisateur. La fonction response permet de définir le résultat à fournir dans la liste.

La propriété minLength peut être utile afin d’éviter d’exécuter des requêtes retournant des résultats trop importants et n’ayant que peu de sens. Elle peut être combinée avec l’ajout d’un TOP(20) dans la requête SQL côté code behind si nécessaire (une liste de propositions d’auto-complétion est en général conçue pour une dizaine ou vingtaine de résultats au maximum).

>> Paramètres

Ne pas oublier d’activer le mode Ajax : dans l’onglet Formulaire du process, cliquer sur Configuration du formulaire (roue dentée dans la barre d’outil) puis dans l’onglet Général, cocher l’option Activer le mode Ajax (tout en bas).

Cette façon de faire me vient du sujet suivant : https://discuss.workflowgen.com/t/how-to-implement-ajax-to-call-net-code-behind-methods/230.

Cordialement,
Quentin

1 Like

Bonjour @qdurand ,

C’est exactement la solution que je recherchais, elle fonctionne parfaitement bien.
J’ai du réduire à 2 la valeur de la propriété minLength car la recherche de noms constitué de 2 caractères n’était pas possible sinon et malgré cela l’autocompletion est quasiment instantanée avec un annuaire constitué de près de 10 000 personnes.

Merci encore pour cette solution !

Cordialement,
Pierre