Search code examples
typeahead.jsbootstrap-typeaheadtwitter-typeaheadbloodhound

Typeahead with input created dynamically


i have an input with typeahead with remote source .. it works fine ! so when i try to add new input by Jquery it don't works !

there is my code :

<input name="name" class="form-control typeahead typeaheadFluxClient" type="text">

<script type="text/javascript">
var flux = new Bloodhound({
      datumTokenizer: function(item) {
          return Bloodhound.tokenizers.whitespace(cleanAcronym(item.nom));
      },
      queryTokenizer: function(query) {
          return Bloodhound.tokenizers.whitespace(cleanAcronym(query));
      },
      limit: 10,
      remote: {

        url: 'remote Url !',
        replace: function (url, query) {
          if ($('.typeaheadFluxClient:focus').val()) {
              url += '?title=' + $('.typeaheadFluxClient:focus').val();
          }
          return url;
      },
        ttl:1,
        filter: function(list) {
          return $.map(list, function(ligne) { return {id:ligne.page_id}});
        }

      }
    });
function initTypeAhead(no) {
    var selection='.typeahead';
    if (no) {
        selection = selection+'-'+no;
    }
    $('.typeaheadFluxClient').typeahead({minLength: 1}, {
        name: 'flux',
        displayKey: 'nom',
        source: flux.ttAdapter(),

        templates: {
            empty: [
              'no type ahead',
              '@lang('events.no_typeahead')',
              '<span class="empty-message-details">',
              'no type ahead',
              '</span>',
              '</div>'
            ].join('\n'),
            suggestion: function (datum) {
                var html=datum.nom;

                return html
            }
        }
    });
}
flux.initialize();
initTypeAheadClientFluxPages();

Here i will try to add input with jquery with the same class of typeahead ! but it didn't works :

$( "#addbtn" ).on( "click", function() {
    var count = $( ".associateFluxCLient" ).length;
    var html = `<hr>

                    <div class="form-group">
                        <label for="object" class="col-sm-2 control-label">Nom</label>
                        <div class="col-sm-10">
                            <input name="fluxClientPageTitle[`+count+`]" class="form-control typeahead typeaheadFluxClient" type="text" >  
                        </div>
                    </div>  
`;
    $("#container").append(html);

How can i resolve this ?


Solution

  • You are adding the new input to the DOM dynamically, so the TypeaheadJS library doesn't know the element exists to initialize it.

    In your click event handler for addbtn, you will need to explicitly initialize the new control. I would also pull out the options hash for the typeahead into a separate variable that can be reused (assuming you want to reuse most of the settings).

    var taOptsHash = {
        minLength: 1
    }, {
        name: 'flux',
        displayKey: 'nom',
        source: flux.ttAdapter(),
        templates: {
            empty: [
              'no type ahead',
              '@lang('events.no_typeahead')',
              '<span class="empty-message-details">',
              'no type ahead',
              '</span>',
              '</div>'
            ].join('\n'),
            suggestion: function (datum) {
                var nom = datum.nom;
                return nom;
            }
        }
    };
    

    Once you do that you can change the initTypeAhead function so that you can reuse it. ** I removed the original variable you are passing in because you don't actually use it anywhere in the function:

    function initTypeAhead(optsHash) {
        $('.typeaheadFluxClient').typeahead(optsHash);
    }
    

    Then you can change your click event handler to explicitly call the initialization. ** I made a few changes to the code you provided to fix some syntax errors:

    $( "#addbtn" ).on( "click", function() {
        var count = $( ".associateFluxCLient" ).length;
        var newEl = '<hr>';
            newEl += '<div class="form-group">';
            newEl += '<label for="object" class="col-sm-2 control-label">Nom</label>';
            newEl += '<div class="col-sm-10">'
            newEl += '<input id="fluxClientPageTitle[` + count + `]" name="fluxClientPageTitle[` + count + `]" class="form-control typeahead typeaheadFluxClient" type="text" >';  
            newEl += '</div>';
            newEl += '</div>';
        $("#container").append(newEl);
        initTypeAhead(taOptsHash);
    });
    

    In the end, this is just one way to possibly handle it. The root issue is that you have to plan to handle any elements that you are adding to the DOM dynamically. Check out this question for some more information.