Bonjour à vous, je viens vour voir parce que j'ai un autre petit soucis. Je suis actuellement en train de développer un petit système pour gérer mes articles et mes fournisseurs et j'aurais besoin que, lorsque je crée un dossier d'articles (une commande rentrante par exemple), d'attribuer automatique une fournisseur à ce dossier. Pour celà j'aurais aimé faire une recherche dans un champ text qui, selon ce que je rentre, me retournerait une liste de résultats sur lesquels je pourrais cliquer (un seul choix) et auto remplir le champ texte.

Mon code de base est réalisé avec CodeIgniter et voici mes fichiers :

La partie formulaire pour le fournisseur :

<div class="form-group">
    {{ form.label('Fournisseur', 'provider') }}
    <div class="input-group">
            <span class="input-group-addon"><span class="fa fa-truck" aria-hidden="true"></span></span>
        <input type="text" class="form-control" value="{{ provider_value }}" name="provider" id="inputString" placeHolder="Nom du fournisseur" />
        <div class="suggestionsBox" id="suggestions" style="display: none;">
            <div class="suggestionList" id="autoSuggestionsList"></div>
        </div>
    </div>
</div>

La partie javascript :

<script type="text/javascript">
    function lookup(inputString)
    {
        if(inputString.length == 0)
        {
            // si le champs texte est vide
            $('#suggestions').hide(); // on cache les suggestions
        }
        else
        {
            // sinon
            $.post("{{ site_url('ajax/fournisseurs') }}", {queryString: ""+inputString+""}, function(data)
            {
                // on envoie la valeur du champ texte dans la variable post queryString au fichier ajax.php
                if(data.length >0)
                {
                    $('#suggestions').show(); // si il y a un retour, on affiche la liste
                    $('#autoSuggestionsList').html(data); // et on remplit la liste des données
                }
            });
        }
    }

    function fill(thisValue)
    {
        // remplir le champ texte si une suggestion est cliquée
        $('#inputString').val(thisValue);
        setTimeout("$('#suggestions').hide();", 200);
    }

    $(document).ready( function ()
    {
        $("input#inputString").keyup( function()
        {
            // si on presse une touche du clavier en étant dans le champ texte qui a pour id inputString
            lookup($(this).val())
        });
        $("input#inputString").blur( function()
        {
            // si le champ texte perd le focus
            fill()
        });
    });
</script>

La partie Ajax :

public function providers()
    {
        //  On récupère la liste des fournisseurs
        $this->load->model('providers_model');

        if( isset($_POST['provider'] )
        {
            if( strlen($_POST['provider']) > 0 )
            {
                $prodivers = $this->providers_model->search_providers($_POST['provider'], TRUE));

                $data = [
                    'providers' =>  $providers,
                ];

                $this->twig->display('ajax/providers.twig', $data);
            }
        }
    }

et la vue des résultats :

{% if providers is not empty %}
    {% for provider in providers %}
        <li  onClick="fill({{ provider.p_name }});">{{ provider.p_title }} {{ provider.p_name }}</li>
        {% endfor %}
{% endif %}

13 réponses


Alexandre #lbac
Auteur
Réponse acceptée

Au final je me suis basé sur jquery-ui pour réaliser ceci. Ca m'a demandé beaucoup moins de code et c'est tout aussi efficace :)

typeaheadjs fait ça très bien

Mais c'est parfait ça =D

Maintenant ma question sera, comment je fais pour faire passer mes données récupérées en php dans ce tableau JS ? (Oui je suis vraiment mauvais en JS...)

Je précise que je ne cherche pas à ce qu'on me fasse le script mais j'aimerais bien avoir les éléments nécessaires pour réaliser celà :)

Côté JS

var providers = new Bloodhound({
  datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
  queryTokenizer: Bloodhound.tokenizers.whitespace,
  remote: '/ton_url/%QUERY.json'
});

providers.initialize();

$('#ton_formulaire')
  .typeahead(null, {
    name: 'providers',
    displayKey: 'value',
    source: providers.ttAdapter()
  })
  .on('typeahead:selected',function(obj, datum, name){
     //ta logique, la valeur sélectionnée est dans datum
     console.log(datum);
  });

Pour php, tu gère la requête GET /ton_url/%QUERY.json
et tu retourne un json

Ok d'accord :)

Je vais tenter ça et je reviens poster mon retour :)

Une question du coup, selon ton code je suis censé réaliser mon json comment ?

Je pensais à

<?php
json_encode(array('datum' => $provider['p_name'], 'name' =>$provider['p_id']));

Mais pourrais tu m'expliquer cette partie du code ?

<script>
.on('typeahead:selected',function(obj, datum, name){
     //ta logique, la valeur sélectionnée est dans datum
     console.log(datum);
  });
</script>

typeahead:selected est un événement qui est déclenché quand une entrée de l'autosuggest est selectionnée, à toi d'y inclure ta logique.

Le json retourné par php doit ressembler à ça :

[
    {id:"1", value: "toto"},
    {id:"2", value: "michel"}
];

D'accord, et id étant l'id du fournisseur et value son nom si je suis bien ?

Oui, tout à fait (je voulais juste mettre oui mais c'est pas assez long)

Rebonjour ^^

Ma question maintenant est comment générer un json selon ton format ?

Actuellement le seul json que j'arrive à produire est de type

string '{"1":"Salle des Ventes Pollestres"}'

Je m'y prends de cette façon :

$providers = $this->providers_model->search_providers('pollestres', TRUE);

        $providers_array = array();
        foreach( $providers as $list )
        {
            $providers_array += [
                $list['p_id']    => $list['p_title'] . ' ' . $list['p_name'],
            ];
        }

        var_dump(json_encode($providers_array));

Le var_dump étant pour afficher le résultat avant essai ^^

Ca me paraît bien, mes compétences s'arrêtent là, je ne connait pas codeigniter et sa gestion du json.

Je dois avoir un soucis au niveau de l'installation alors. Car le script me retourne un "undefined" quand je remplis mon champ.

Pour résumer mon installation j'ai inclus :

<script src="{{ base_url() }}js/bloodhound.min.js"></script>
<script src="{{ base_url() }}js/typeahead.bundle.min.js"></script>
<script src="{{ base_url() }}js/typeahead.jquery.min.js"></script>

<script type="text/javascript">
    var providers = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        remote: '{{ site_url('ajax/providers') }}'
    });

    providers.initialize();

    $('.input-group .form-control')
            .typeahead({
                hint: true,
                highlight: true,
                minLength: 1
            },
            {
                name: 'providers',
                displayKey: 'value',
                source: providers.ttAdapter()
            })
            .on('typeahead:selected',function(obj, datum, name){
                console.log(datum);
            });
</script>

Dans ma page, voici mon formulaire :

<div class="input-group">
       <span class="input-group-addon"><span class="fa fa-truck" aria-hidden="true"></span></span>
                     {{ form.input('provider', provider_value, 'text', 'form-control', 'Nom du fournisseur') }}
                    </div>

qui retourne

<input type="text" name="provider" class="form-control" value="" id="provider" placeholder="Nom du fournisseur" autocomplete="off">

Aurais-je oublé un ou des fichiers ? Merci encore pour ton aide :)

Rien à faire je n'arrive pas à avancer avec :/
De plus mon formulaire refuse de s'exécuter avec le code JS :/

Bonjour, qu'indique le code js, peut-on tester le code en ligne?