Autocomplete popup smart search list... how to recreate with new options after it was rendered?


#1

I have created an autocomplete popup smart search list using the code below:

 self.autocompleteStandaloneAjax = app.autocomplete.create({
          openIn: 'popup', //open in page
          openerEl: '#destination-ajax', //link that opens autocomplete
          multiple: true, //allow multiple values
          valueProperty: 'id', //object's "value" property name
          textProperty: 'name', //object's "text" property name
          limit: 50,
          preloader: true, //enable preloader
          source: function (query, render) {
            var autocomplete = this;
            var results = [];
            if (query.length === 0) {
              render(results);
              return;
            }
            // Show Preloader
            autocomplete.preloaderShow();
            // Do Ajax request to Autocomplete data
            app.request({
              url: 'data_1.json',
              method: 'GET',
              dataType: 'json',
              //send "query" to server. Useful in case you generate response dynamically
              data: {
                query: query
              },
              success: function (data) {
                // Find matched items
                for (var i = 0; i < data.length; i++) {
                  if (data[i].name.toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(data[i]);
                }
                // Hide Preoloader
                autocomplete.preloaderHide();
                // Render items by passing array with result items
                render(results);
              }
            });
          },
          on: {
            change: function (value) {
              var itemText = [],
                  inputValue = [];
              for (var i = 0; i < value.length; i++) {
                itemText.push(value[i].name);
                inputValue.push(value[i].id);
              }
              // Add item text value to item-after
              $('#destination-ajax').find('.item-after').text(itemText.join(', '));
              // Add item value to input value
              $('#destination-ajax').find('input').val(inputValue.join(', '));
            },
          },
        });

and I was able to get the value I type in the search using this:

open: function (value) {

          $('.searchbar-input-wrap input[type=search]').on('input', function() {

          val = $('.searchbar-input-wrap input[type=search]').val();

          if (val.length > 0)
          {

          Ajax call to request new data...

          }

…

I just want to recreate the rendered data options if the val.length > 0 with new options
this means when I type something in the search box then the new options are loaded via Ajax calling a new JSON that has the new options to be displayed and searched …and the initial options are overwritten with this new data…

my question is how can I do this…?

I tried this code below and the data in the console it is showing correct but the new rendered data does not updates the previous one…

here it is the code

Ajax call to request new data…

        query = $('.searchbar-input-wrap input[type=search]').val();
        app.request({
          url: 'data_2.json',
          method: 'GET',
          dataType: 'json',
          //send "query" to server. Useful in case you generate response dynamically
          data: {
            query: query
          },
          success: function (data) {
            // Find matched item

            console.log(data.length);

            for (var i = 0; i < data.length; i++) {
              //alert(data[i].name.toLowerCase().indexOf(query.toLowerCase()));
              if (data[i].name.toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(data[i]);
            }

            console.log(results);
            render(results);
          }
        });

if you see render(results) it is ok and show in the console the new data options, I just want to overwrite the previous options with these…

I just want to refresh the initial rendered data with new data… after an actions is happening in this case when I type something on the search box…

any clues how to achieve this?
big thanks


#2

I don’t understand, what are you using Autocomplete or Smart Select? In case of autocomplete there is a demo on how to populate data via Ajax https://github.com/framework7io/framework7/blob/master/kitchen-sink/pages/autocomplete.html#L310


#3

I was using smart select in the beginning but I needed something that can be feed the data from a Json so I decided to use the autocomplete to create a list like the smart select list…

I used the sample you mention in autocomplete.html

the problem it is that once the list options are generated after the results are rendered, I need to generate new options that have to replace the initial ones…

I know it sounds little confusing why to change the options after there are already rendered… but in my case I need to display some options when the popup list is opened as default options … but when the user start typing a word in the search bar then these initial options need to be replaced by the new ones calling another JSON file that contains the new options to be rendered and replace the initial ones…

in my application for instance I need this because the user select a destination like
beach, night life, museums etc… but if she/he knows the destination then he/she start typing it and then the options need to be refreshed or replaced with new ones in this case cities names…

so my question is: is there a way to regenerate the initial options rendered with new data options?

I am using ajax to call the second JSON after the user start typing and in the console.log it shows this new data but the initial options are not being replaced by the new ones in the search list…

any ideas to achieve this?


#4

Just idea – use autocomplete with ajax data (last item in kitchen sink - autocomplete) but change code to show your predefined data with openinng autocomplete, user may select it or use searchbar to show ajax loaded data


#5

Thank you …

But I tried that too predefined data and new one after using the searchbar both are loaded via Ajax…

the problem is not load the data the problem it is that render(results) does not overwrite the predefined data options with the new ones when user use the searchbar…

in the console I can see the new data but it is not rendered into the list…

so… any ideas how to re-render the predefined data with the new one?
render(results) shows the new data in the console but does not update or overwrite the initial predefined one…

any ideas?


#6

I have found.
Use parameter requestSourceOnOpen: true;

Below part of code from Kitchens-sink that I mentioned above. It opens autocomplete with custom datat (var data and shows data from ajax query result when user types a query to search input field…

        self.autocompleteStandaloneAjax = app.autocomplete.create({
          openIn: 'page', //open in page
          openerEl: '#autocomplete-standalone-ajax', //link that opens autocomplete
          multiple: true, //allow multiple values
          valueProperty: 'id', //object's "value" property name
          textProperty: 'name', //object's "text" property name
          limit: 50,
          preloader: true, //enable preloader
          requestSourceOnOpen: true,
          source: function (query, render) {
              
                      var data = [
  {
    "id": 0,
    "name": "A# .NET"
  },
  {
    "id": 1,
    "name": "A# (Axiom)"
  },
  {
    "id": 2,
    "name": "A-0 System"
  },
  {
    "id": 3,
    "name": "A+"
  },
  {
    "id": 4,
    "name": "A++"
  },
  {
    "id": 5,
    "name": "ABAP"
  },
  {
    "id": 6,
    "name": "ABC"
  },
  {
    "id": 7,
    "name": "ABC ALGOL"
  }]; 

            var autocomplete = this;
            var results = [];
            //console.log(data);
            if (query.length === 0) {
              results = data;      
              render(results);
              return;
            }
            // Show Preloader
            autocomplete.preloaderShow();
            // Do Ajax request to Autocomplete data

#7

nice thanks I will try to do this and let you know the results! I hope this can work!!
big thanks


#8

I think it is working perfectly this way!!! just as I want it…
predefined data as initial thing and then when typing in the search bar it looks up for the data loaded via ajax!

Great solution, Big thanks


#9

Hi I have a Question:

How validate this input and how I set an default value


#10

you can validate the input using
…
on: {
change: function (value) { …

and default value

…
var data = [
{
“id”: “11123123”,
“name”: “London, MDZA”
}];
…

full sample below that has default values id and name with. London,you can increase the size of the data json object with more entries and then on change you can read the value and id selected and do whatever you want… in my sample I read an external json with cities around the world this json will be read when searching but the default value will be shown when opening before the search occurs…

full sample:

    self.autocompleteStandaloneAjax = app.autocomplete.create({
      openIn: 'popup', //open in page
      openerEl: '#destination-ajax', //link that opens autocomplete
      multiple: false, //allow multiple values
      closeOnSelect: true, //go back after we select something
      valueProperty: 'id', //object's "value" property name
      textProperty: 'name', //object's "text" property name
      limit: 50,
      requestSourceOnOpen: true,
      preloader: true, //enable preloader
      source: function (query, render) {

      var data = [
        {
          "id": "11123123",
          "name": "London, MDZA"
        }]; 

        var autocomplete = this;
        var results = [];

        if (query.length === 0) {
          results = data;      
          render(results);
          return;
        }
        // Show Preloader
        autocomplete.preloaderShow();
        // Do Ajax request to Autocomplete data
        app.request({
          url: 'jsons/cities_en.json',
          method: 'GET',
          dataType: 'json',
          //send "query" to server. Useful in case you generate response dynamically
          data: {
            query: query
          },
          success: function (data) {
            // Find matched items
            for (var i = 0; i < data.length; i++) {
              if (data[i].name.toLowerCase().indexOf(query.toLowerCase()) >= 0) results.push(data[i]);
            }
            // Hide Preoloader
            autocomplete.preloaderHide();
            // Render items by passing array with result items
            render(results);
          }
        });
      },
      on: {
        change: function (value) {
          var itemText = [],
              inputValue = [];
          for (var i = 0; i < value.length; i++) {
            console.log(value[i].id);
            itemText.push(value[i].name);
            inputValue.push(value[i].id);
          }
      
          // Add item text value to item-after
          $('#destination-ajax').find('.item-after').text(itemText.join(', '));
          // Add item value to input value
          $('#destination-ajax').find('input').val(inputValue.join(', '));
        },
      },
    });

:slight_smile: