1

Here is the way we initialize autocomplete (jQuery) for dynamically inserted element:

$(function() {
  setTimeout(function(){
    $("[id^='requisition_material_items_attributes_'][id$='_item_name_autocomplete']").each(function (){
       $(this).autocomplete({
        minLength: 1,
        source: $(this).data('autocomplete-source'),
        select: function(event, ui) {
            $(this).val(ui.item.value);
        }
      });
    });
  }, 5000);
});

Here setTimeout (5 second delay) allows autocomplete initialization for first dynamically inserted element. However the initialization does not work for second inserted element and the autocomplete does not kick in for second element. How to fix the JS code above to make it working for second elements and on?

Update

The solution provided by jQuery autocomplete for dynamically created inputs (so called duplicate case) is not working here because it is for a different issue. In duplicate case the problem was solved by adding the initialization of autocomplete when the new element was generated with JavaScript. In our case, the new element was generated by Rails and can not be inserted with autocomplete initialization code into it when generating. In our case autocomplete works for first inserted element and does not for second element. Our question is to make autocomplete initialize for second element and on.

Update

Rails view for item_name_autocomplete:

<%= f.input :item_name_autocomplete, :label => t("Item Name"), :input_html => { data: {autocomplete_source: SUBURI + base_materialx.autocomplete_parts_path}},:placeholder => t("Enter Part Name Keyword"), :required => true  %>
halfer
  • 19,824
  • 17
  • 99
  • 186
user938363
  • 9,990
  • 38
  • 137
  • 303

2 Answers2

2

setTimeout calls the function after a specified delay, it doesn't set an interval, you could use the setInterval function, but it's a terrible idea in this case. You should select the target generated elements whenever you generate them and then call the method on those specific elements. There is no solid/nice way for handling this issue.

Ram
  • 143,282
  • 16
  • 168
  • 197
  • The id of the new element is unknown until it is inserted. – user938363 Oct 25 '14 at 23:40
  • @user938363 How do you generate the elements? – Ram Oct 25 '14 at 23:41
  • The element is generated and inserted by Rails (3.2) and not done by jquery. We are at the step which initializes the autocomplete for newly inserted elements. – user938363 Oct 25 '14 at 23:51
  • Here is the code adding autocomplete to the element in Rails view: <%= f.input :item_name_autocomplete, :label => t("Item Name"), :input_html => { data: {autocomplete_source: SUBURI + base_materialx.autocomplete_parts_path}},:placeholder => t("Enter Part Name Keyword"), :required => true %> – user938363 Oct 25 '14 at 23:53
  • @user938363 Well, in that case there is no dynamically generated elements(_client-side-wise_). The document ready is enough. Just add a generic className to the elements and then `$('.aClassName').autocomplete( ... )` – Ram Oct 26 '14 at 00:02
  • @@Vohuman, that's where we stuck. Somehow our js code was not able to locate 2nd inserted element (so no autocomplete initialization). The inserted element has unique ID. Without setTimeout, even 1st element could not be located. – user938363 Oct 26 '14 at 00:19
  • We tried replacing setTiemout with a custom function and call the custom function within the block, this did not locate any element at all. – user938363 Oct 26 '14 at 00:20
  • We used .on (jquery) before for locating inserted elements (more than one elelment. without autocomplete though). But here .on seems not applicable. – user938363 Oct 26 '14 at 00:48
  • @user938363 Well, `on` is used for listening to events. Here there is a timing issue. You generate the elements on the server-side, so it's not generated by client-side JavaScript. Then it's **not** a dynamically generated element. You listen to `ready` event, it's handler is called when the DOM is ready, done. Now you can select the elements. ... – Ram Oct 26 '14 at 00:56
  • ... From now on whatever element you generate using JavaScript(AJAX, User Interaction) is considered dynamically generated. You want to listen to events which is fired by those elements? You use `on`. You want to call a method like the `autocomplete` on them, you select them whenever you generate them. How? You use the power of jQuery as a DOM traversing library. – Ram Oct 26 '14 at 00:56
  • Element is still dynamic. Server is only responsible to generate element in string and use clicks a button to insert the html string when he/she wants to do insertion. Here is how we use .on on dynamic element: $(document).on('change', "[id^='order_order_items_attributes_'][id$='_qty']", function () { .... )}; – user938363 Oct 26 '14 at 02:17
  • setInterval does the job to initialize autocompletes periodically. – user938363 Nov 05 '14 at 04:16
2

Your script need to change extract function callback from setTimeout

I illustrated your case like below, may be helps to get an idea

function registerAutoComplete(elements) {
    return elements.each(function () {
        $(this).autocomplete({
            minLength: 1,
            source: $(this).data('autocomplete-source'),
            select: function (event, ui) {
                $(this).val(ui.item.value);
            }
        });
    });
}

//if you create new autocomplete element with some function 
function createAutocompleteElement() {
    var $control = $('<input />').data('autocomplete-source', [
        "Add the Data Source object here", "Value 1", "Source Value 2", "Source Value 3"]);

    return registerAutoComplete($control);
}

$(function () {
    //this below function sufficient to register autocomplete with specified selector
    registerAutoComplete($("[id^='requisition_material_items_attributes_'][id$='_item_name_autocomplete']"));

    /*// below setTimeout delay call back not required as it runs after dom ready.
    setTimeout(function () {
        registerAutoComplete($("[id^='requisition_material_items_attributes_'][id$='_item_name_autocomplete']"));
    }, 5000);
    */
});
Koti Panga
  • 3,660
  • 2
  • 18
  • 21
  • The generating and inserting of html code (with autocomplete data source) is done in Rails (3.2). The view was inserted with Rails partial view (.html.erb) rendering. I guess we can skip the function createautocompleteElement(). We are at the step which initializes autocomplete for newly inserted element. – user938363 Oct 25 '14 at 23:49
  • You can run `registerAutoComplete` by placing `` at the end of the partial view so that it will register autocomplete to specified selector matched elements. – Koti Panga Oct 25 '14 at 23:56
  • Is there some example we can take a look? We haven't done it before with script in Rails partial view. – user938363 Oct 26 '14 at 00:33
  • 1
    Give a look on these answers, you can get idea: http://stackoverflow.com/questions/3437585/best-way-to-add-page-specific-javascript-in-a-rails-3-app and http://stackoverflow.com/questions/2464595/including-inline-javascript-using-content-for-in-rails – Koti Panga Oct 26 '14 at 05:20