Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

data.src is called 2 times on keypress #72

Closed
srinivas025 opened this issue Sep 11, 2019 · 14 comments
Closed

data.src is called 2 times on keypress #72

srinivas025 opened this issue Sep 11, 2019 · 14 comments
Labels
bug Something isn't working

Comments

@srinivas025
Copy link

Hi, i found an issue when querying in the input box. When i do a keypress, my api is called 2 times which is present in data.src async function. this makes the user experience slow since the search results are not rendered unless i get response from the second call. Please let me know how i can fix this.
Thanks

@srinivas025 srinivas025 added the bug Something isn't working label Sep 11, 2019
@TarekRaafat
Copy link
Owner

Hello @srinivas025,

Please try the below attached file, it has a quick fix and let me know how it went.

autoComplete.js.zip

@argebynogame
Copy link

Hi, firstly thanks for the great package. The file you sent lastly works for me to fix duplicated api calls. But 'afterend', 'ul' elements rendering more than once. For example if I type 4 times , it renders 4 different ul elements with id is 'autoComplete_results_list'. Any idea ?

@TarekRaafat
Copy link
Owner

Hello @argebynogame,

Thanks, man!

Great, I'm glad that we've solved the first issue api multiple calls.

Find the fixed build here

Let's check the second one.

Just kindly provide the below details to help replicate your issues.

  • Any error messages in the JS console
  • The used autoComplete.js code snippet
  • If available, add screenshots

Cheers! :)

@argebynogame
Copy link

argebynogame commented Sep 17, 2019

Hello again @TarekRaafat ,
I will drop some screenshots and code snippet , I hope it works :)
When I typed 'germ' , it finds Germany but every time when i type a letter new 'ul' element created.
And there is no console error.
Thanks in advance :)
Screen Shot 2019-09-17 at 09 22 31
Screen Shot 2019-09-17 at 09 15 45

document.querySelector("#autoComplete").addEventListener("keyup", function(event) {
            const query = document.querySelector("#autoComplete").value;
            if (query !== '') {
                const autoCompletejs = new autoComplete({
                    data: {                              // Data src [Array, Function, Async] | (REQUIRED)
                        src: async () => {
                            // API key token

                            // const token = "this_is_the_API_token_number";
                            // User search query

                            const query = document.querySelector("#autoComplete").value;
                            // Fetch External Data Source
                            const source = await fetch(`https://restcountries.eu/rest/v2/name/${query}`);
                            // Format data into JSON
                            let data = await source.text();
                            // console.log(data);
                            data = JSON.parse(data);
                            // Return Fetched data
                            return data;
                        },
                        key: ["name"],
                        cache: true
                    },
                    // query: {                               // Query Interceptor               | (Optional)
                    //     manipulate: (query) => {
                    //         return query.replace("pizza", "burger");
                    //     }
                    // },
                    sort: (a, b) => {                    // Sort rendered results ascendingly | (Optional)
                        if (a.match < b.match) return -1;
                        if (a.match > b.match) return 1;
                        return 0;
                    },
                    placeHolder: "Please type something ?",     // Place Holder text                 | (Optional)
                    selector: "#autoComplete",           // Input field selector              | (Optional)
                    threshold: 1,                        // Min. Chars length to start Engine | (Optional)
                    debounce: 600,                       // Post duration for engine to start | (Optional)
                    searchEngine: "strict",              // Search Engine type/mode           | (Optional)
                    resultsList: {                       // Rendered results list object      | (Optional)
                        render: true,
                        container: (source) => {
                            const resultsListID = "search_List";
                            source.setAttribute("id", "autoComplete_results_list");
                            return resultsListID;
                        },
                        destination: document.querySelector("#autoComplete"),
                        position: "afterend",
                        element: "ul"
                    },
                    maxResults: 10,                         // Max. number of rendered results | (Optional)
                    highlight: true,                       // Highlight matching results      | (Optional)
                    resultItem: {                          // Rendered result item            | (Optional)
                        content: (data, source) => {
                            let html = `<div class="d-flex align-items-center flex-row"><span><img width="60" alt="${data.match}" src="${data.value.flag}"></span> <span style="margin-left: 2em;">${data.match}</span></div>`;
                            $(source).html(html);
                        },
                        element: "li"
                    },
                    // noResults: () => {                     // Action script on noResults      | (Optional)
                    //     const result = document.createElement("li");
                    //     result.setAttribute("class", "no_result");
                    //     result.setAttribute("tabindex", "1");
                    //     document.querySelector("#autoComplete_results_list").appendChild(result);
                    // },
                    // onSelection: feedback => {             // Action script onSelection event | (Optional)
                    //     console.log(feedback.selection.value.image_url);
                    // }
                });
            }

        });```

@TarekRaafat
Copy link
Owner

Try removing the below lines and let me know how it went.

document.querySelector("#autoComplete").addEventListener("keyup", function(event) {
            const query = document.querySelector("#autoComplete").value;
            if (query !== '') {

@argebynogame
Copy link

Hey, if I remove these lines autoComplete try to run without a search query then it fails .
it is a data.json() error :) And then I try to search nothing happen because of error.
Screen Shot 2019-09-17 at 10 37 38

@srinivas025
Copy link
Author

srinivas025 commented Sep 17, 2019

Hi @TarekRaafat,
I used the used that you sent above and seeing an error on key press.
Uncaught TypeError: _this2.dataSrc.then is not a function
at run (autocomplete.js:365)
at HTMLInputElement. (autocomplete.js:379)
at autocomplete.js:315
I dont see any api call being called.. when i console logged _this2, i saw cached values in dataSrc array even though i have set cache to false.
Please let me know if you need more details from me. Appreciate your effort.
Thanks

@TarekRaafat
Copy link
Owner

Hello @srinivas02,

If you're using this.dataSrc it's changed to this.dataStream.
If not please provide the below details to help replicate your issue.

  • The used autoComplete.js code snippet

Cheers! :)

@srinivas025
Copy link
Author

srinivas025 commented Sep 17, 2019

@TarekRaafat
I used the new fixed code and getting the error
Uncaught TypeError: Cannot read property 'then' of undefined
at run (autocomplete.js:365)
at HTMLInputElement. (autocomplete.js:379)
at autocomplete.js:315
I dont see any api call being called here.
This is my code

var autoCompletejs = new autoComplete({
                data: {
                    src: async function() {
                        // Loading placeholder text
                        if($("#autoComplete").is(':focus')){
                            console.log("focus");
                            $areaDocsSearch.find('.img-loader').show();
                        }
                        const query = document.querySelector("#autoComplete").value;
                        if (query.length == 1){
                            $areaDocsSearch.find('#autoComplete_results_list').removeClass('back-drop');
                        }
                        document
                            .querySelector("#autoComplete")
                            .setAttribute("placeholder", "Loading...");

                        const source = await fetch(
                            "/Help/searchReadme?search="+query
                        );
                        let results = source.results;
                        const data = await source.json();
                        // Post loading placeholder text
                        document
                            .querySelector("#autoComplete")
                            .setAttribute("placeholder", "Search help docs");
                        return data.results;
                    },
                    key: ["title"],
                    cache: false
                },
                sort: (a, b) => {
                    if (a.match < b.match) return -1;
                    if (a.match > b.match) return 1;
                    return 0;
                },
                placeHolder: "Search help docs",
                selector: "#autoComplete",
                threshold: 0,
                debounce: 300,
                searchEngine: "strict",
                highlight: true,
                maxResults: 10,
                resultsList: {
                    render: true,
                    container: source => {
                      source.setAttribute("id", "autoComplete_results_list");
                    },
                    destination: document.querySelector("#form_docs_search"),
                    position: "afterend",
                    element: "ul"
                },
                resultItem: {
                    content: (data, source) => {
                        $areaDocsSearch.find('.img-loader').hide();
                        source.innerHTML = data.match;
                        if ($areaDocsSearch.find('#autoComplete_results_list li').length == 0){
                            $areaDocsSearch.find('#autoComplete_results_list').removeClass('back-drop');
                        }
                        else{
                            $areaDocsSearch.find('#autoComplete_results_list').addClass('back-drop');
                        }
                    },
                    element: "li"
                },
                noResults: () => {
                    const result = document.createElement("li");
                    $areaDocsSearch.find('#autoComplete_results_list').removeClass('back-drop');
                    result.setAttribute("class", "no_result");
                    result.setAttribute("tabindex", "1");
                    result.innerHTML = "No Results";
                    document.querySelector("#autoComplete_results_list").appendChild(result);
                    $areaDocsSearch.find('.img-loader').hide();
                },
                onSelection: feedback => {
                    console.log(feedback)
                    const selection = feedback.selection.value.url;
                    window.open(selection, '_blank');
                    // Clear Input
                    document.querySelector("#autoComplete").value = "";
                }
            });

when i console logged _this2, i got this as response
```
data:
cache: false
key: ["title"]
src: ƒ src()
__proto__: Object
dataStream: undefined
dataType: true
debounce: 300
highlight: true
maxResults: 10
noResults: () => {…}
onSelection: feedback => {…}
placeHolder: "Search help docs"
query: undefined
resultItem: {content: ƒ, element: "li"}
resultsList: {render: true, shadowRoot: document, view: ul#autoComplete_results_list, navigation: false}
searchEngine: "strict"
selector: "#autoComplete"
sort: (a, b) => {…}
threshold: 0
trigger: {event: Array(1), condition: false}
```

@srinivas025
Copy link
Author

srinivas025 commented Sep 17, 2019

Hi @TarekRaafat
I finally made it to work by changing the run function to this

var run = function run(event) {
          if (!_this2.data.cache) {
          	_this2.dataStream = _this2.data.src();
        	_this2.dataType = _this2.dataStream instanceof Promise;
            if (_this2.dataType) {
              _this2.dataStream.then(function (response) {
	            _this2.dataStream = response;
	            exec(event);
	          });
            } else {
              _this2.dataStream = _this2.dataStream;
              exec(event);
            }
          } else {
            exec(event);
          }
        };

@TarekRaafat
Copy link
Owner

@argebynogame try this code and let me know how it went.

const autoCompletejs = new autoComplete({
  data: {
    src: async function () {
      // Fetch External Data Source
      const source = await fetch("https://restcountries.eu/rest/v2/all");
      // Format data into JSON
      const data = await source.json();
      // Return Fetched data
      return data;
    },
    key: ["name"],
  },
});

@TarekRaafat
Copy link
Owner

@srinivas025 did you try first to switch the cache to true?

@srinivas025
Copy link
Author

@TarekRaafat i dont want to cache the data because i dont have a call to get all results.

@TarekRaafat
Copy link
Owner

Hello @srinivas025 & @argebynogame,

I've entirely re-factored the data handling section.

Now the data.src never calls theAPI if set not to be cached until you start typing in-order to provide the API a query.

Previously it used to initiate empty API calls that caused that issue in addition to a bug that existed in the non-cached data.src that has been solved as well thanks to @braco.

Kindly check the new build it should work as expected and let me know how it went.

Cheers! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants