How can I trigger a data fetch as the input of the SelectField search box changes?

#1

We have 100000+ records and have found that fetching them and then loading them all into a SelectField causes performance issues on the page. So instead, we’d like to limit the fetch but update the filter and re-fetch the data as the user types in the search box. Is there a way to do that with this component or is a text field with typeahead better suited for this use case?

0 Likes

#2

If you want to use the SelectField, the way to go is to paginate the SelectField, which does automatically what you are describing. You can set the pagination config to a number such as 20. I believe this will cause the dropdown to be lazy loaded, so that when you scroll down to the bottom of the list it will load the next 20 options.

Alternately, you can use text field with typeahead, although this is a little trickier to set up, as you have to provide functions to generate the suggestions list and process the selected item.

0 Likes

#3

Thanks Josh. I tried that with fetching ~130,000 records, and while it doesn’t crash my browser, it takes the page 10+ seconds to load and the component is not usable. I’m seeing this error in the console:

Collection.js:346 Uncaught RangeError: Maximum call stack size exceeded
at Collection.remove (Collection.js:346)
at Collection.processLoadSuccess (Collection.js:153)
at Collection.onLoadSuccess (Loadable.js:601)
at C3Request.handleResponse (Request.js:397)
at Connection.complete (Connection.js:250)
at fire (jquery.js:3099)
at Object.fireWith (jquery.js:3211)
at done (jquery.js:8279)
at XMLHttpRequest. (jquery.js:8605)

0 Likes

#4

If you are ok with using the field.Text component you can use the typeAheadOptions.minLength config to make sure you require more characters before searching. Maybe 3 would be enough to limit the results in your case?

0 Likes

#5

I’m open to it, but as @josh.nathanson alluded to above, I’m not sure how to go about selecting an option from the type-ahead results and processing it. Type-ahead seems to return strings of the name field matching the search term, but then I’d need to get the object or ID of the item selected and trigger some actions with it.

By the way, the error above happens before I even click the select field to search and filter.

0 Likes

#6

The select field component currently does not support remote loading as you would like. Answering your question about how to trigger You can add a behavior:

            {
                  "query": "[your_select_field_id]",
                  "trigger": "change",
                  "action": {
                        "type": "[your_action_id]"
                  }
            }

I would suggest to give Field.Text a try as @Dylan recommended if you have a huge data source. Also, it’s better user experience since most likely users would not scroll through your dropdown. And also you can use the same behavior as mentioned above because it will trigger the change event when the field is updated

Example:

{
    "component": "field.Text",
    "name": "name",
    "typeahead" : {
        "c3type" : "ApplicationAlert"
    },
    "id": "nameField"
}
0 Likes

#7

Thanks @tonycho.

Since the typeahead searches the name field, the results are matching strings. Is there a way to specify that the typeahead return objects including both id and name?

0 Likes

#8

Try listening to the typeahead:selected event on the dom element instead of the change event on the Text component. your action should be called with the selected object with the param

{
        "query": "$ input[name='currentType.c3Type']", // jquery selector of your input field. e.x. #id, .cssClassName
        "trigger": "typeahead:selected",
        "action": {
            "type": "[your_action_id]"
        }
}
0 Likes

#9

Thanks that helped! I’m now able to trigger the actions on selection, but I’m still not clear on how I would get the id of the selected item because I have just the matching names rather than objects with id and name.

e.g. typeahead triggers something like:
MyType.evaluate({filter:"startsWith(upperCase(name),upperCase('abc'))",projection:"unique(name)",limit:25})

the response looks something like:
{ "tuples" : [ { "cells" : [ { "str" : "abc1" } ] }, { "cells" : [ { "str" : "abc2" } ] }, { "cells" : [ { "str" : "abc3" } ] } ], "count" : 3, "hasMore" : false }

0 Likes

#10

@asaf
What’s returned as the parameters passed into your Action.dispatch function? Your action should have a dispatch function and I would like to know what’s in the arguments.

The dispatch function will be called in your action when the event is triggered

dispatch: function() {
}
0 Likes

#11

@tonycho

dispatch: function (page, args) { … }

args:
{ "type":"typeahead:selected", "timeStamp":1518201600650, "jQuery21406875073542272878":true, "isTrigger":3, "namespace":"", "namespace_re":null, "target":{}, "delegateTarget":{"sizzle1518201579450":{"parentNode":[439,94,true]}}, "currentTarget":{}, "handleObj":{ "type":"typeahead:selected", "origType":"typeahead:selected", "guid":51, "selector":"input[name='organization']", "needsContext":false, "namespace":"Dashboard.delegateEventsEnergyManagement"} }

I can get the selected value from args.target.value, but that’s the just a string with the name of the selected item.

0 Likes

#12

Is it the entire object? In your example args.target is empty but you’re saying you can get it from args.target.value. Indeed, usually args.currentTarget.value should return the selected object

Can you tell me what your use case is so that I can help you better? Like what are you going to do with the selected value

Thanks

0 Likes