We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

Set delay search when typing and minimum character count?

Using a data manager with UrlAdaptor for searching a huge list of data that we have - but every time you type, no matter how fast it hits the server, this causes a significant amount of unneeded network traffic and queries on my database. I cannot seem to find a setting to have a delay, ie 200-300ms from when you stop typing for it to run the search, that way if I search for "something" - so long as I type it continuously - it will do one search with the full word vs right now it hits the server 9 times...

I was trying to override this with a custom adapter, since I have a "delay callback" pattern for this already in other keyword searching through my system - but was hoping to not have to tweak that...

3 Replies

SP Sureshkumar P Syncfusion Team November 1, 2019 09:39 AM UTC

Hi Nayt, 
 
Greetings from Syncfusion support. 
 
We have validated your requirement. we can able to restrict the search based on the given text length and timeout. Kindly refer the below code block. 
 
[search string length] 
 
// initialize the MultiSelect component 
let listObj: MultiSelect = new MultiSelect({ 
    // set placeholder to MultiSelect input element 
    placeholder: 'Select countries', 
    // set the countries data to dataSource property 
    dataSource: (data as any).countries, 
    // bind the Query instance to query property 
    query: new Query(), 
    // map the appropriate columns to fields property 
    fields: { text: 'Name', value: 'Code' }, 
    // set true for enable the filtering support. 
    allowFiltering: true, 
    // bind the filtering event 
    filtering: (e: FilteringEventArgs) => { 
        e.preventDefaultAction = true; 
        let query: Query = new Query(); 
        // frame the query based on search string length with filter type.              
        query = (e.text.length > 3) ? query.where('Name''startswith', e.text, true) : query; 
        // pass the filter data source, filter query to updateData method.  
        e.updateData((data as any).countries, query); 
 
    } 
}); 
listObj.appendTo('#list'); 
 
[timeout] 
 
// initialize the MultiSelect component 
let listObj: MultiSelect = new MultiSelect({ 
    // set placeholder to MultiSelect input element 
    placeholder: 'Select countries', 
    // set the countries data to dataSource property 
    dataSource: (data as any).countries, 
    // bind the Query instance to query property 
    query: new Query(), 
    // map the appropriate columns to fields property 
    fields: { text: 'Name', value: 'Code' }, 
    // set true for enable the filtering support. 
    allowFiltering: true, 
    // bind the filtering event 
    filtering: (e: FilteringEventArgs) => { 
        e.preventDefaultAction = true; 
        let query: Query = new Query(); 
        // frame the query based on search string with setTimeOut filter type.              
        query = (e.text !== "") ? query.where('Name''startswith', e.text, true) : query; 
        // pass the filter data source, filter query to updateData method.  
        setTimeout(function () { 
            e.updateData((data as any).countries, query); 
        }, 1000) 
 
    } 
}); 
listObj.appendTo('#list'); 
 
 
 
 
We created a sample based on your requirement. please refer the sample here: https://stackblitz.com/edit/ro1bde-3s5app?file=index.ts  
 
Regards, 
Sureshkumar P 



NG Nayt Grochowski November 1, 2019 05:23 PM UTC

One more question - since it does the search as soon as you click on the box and doesn't call "filtering" callback when the search field is empty - any way to have it not do a search at all until you start typing?

I can handled that server-side really if needed and return empty and update the no records found template I think.

The "filtering" attribute is what I was missing though and this really helped - Just a quick note if anyone else asks about this - the way you set this up right now for delayed search, will still trigger the run for every keystroke, since set time, just delays the call. 

Here is a tweak to the code that I put in place to wipe out the current "setTimeout" so that only the last one runs (FYI - I code everything in ES6...)

const dataManager = new ej.data.DataManager({
    adaptor: new ej.data.UrlAdaptor(),
    crossDomain: true,
    headers: headers,
    url: site_settings.api + `v1/poc/advanceSearch/filterSource/${_which}`,
});

let timeoutPointer = null;
const lookupSelector = new ej.dropdowns.MultiSelect({
    dataSource: dataManager,
    query: new ej.data.Query().addParams('filterSource', filterData.filterSource),
    allowFiltering: true,
    filtering: function (e) {
        e.preventDefaultAction = true;

        if (timeoutPointer) { clearTimeout(timeoutPointer); }
        timeoutPointer = setTimeout(() => {
            const query = new ej.data.Query()
                .addParams('filterSource', filterData.filterSource)
                .addParams('keyword', e.text)
                ;

            e.updateData(dataManager, query);
        }, 400);
    },

    fields: {
        text: 'name',
        value: 'code'
    },

    filterBarPlaceholder: 'Search',
    filterType: 'Contains',
    mode: 'CheckBox',

    showClearButton: true,
    showDropDownIcon: true,
    showSelectAll: false,
});
lookupSelector.appendTo(`#filter-value-${groupIndex}-${rowIndex}`);



SP Sureshkumar P Syncfusion Team November 4, 2019 10:09 AM UTC

Hi Nayt, 
 
We have checked the reported requirement. We would like to inform you that, filtering event will be triggered when you start searching on the character.  When you click on the input element, focus event will trigger. From the focus event we can get the multiselect value by using below code, 
 
focus: function(args) { 
    console.log(this.value) 
} 
 
 
Also, in multi-select when you click on the input element then request will be sent to the server. If you want to send requests only when filtering, then we suggest disabling the openOnClick property. 
 
openOnClick: false, 
 
 
Regards, 
Sureshkumar P 


Loader.
Live Chat Icon For mobile
Up arrow icon