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

search delay #58

Closed
rhernandez-itemsoft opened this issue Dec 10, 2021 · 3 comments
Closed

search delay #58

rhernandez-itemsoft opened this issue Dec 10, 2021 · 3 comments
Assignees
Labels
enhancement New feature or request

Comments

@rhernandez-itemsoft
Copy link

How can I add a delay in the execution of "futureSearchFn" so that it does not execute while I am typing.

Currently every character I type executes a call to "futureSearchFn".
image

I would like there to be a property called "searchDelay" which would prevent "futureSearchFn" from being called with every character that is typed, and will only call "futureSearchFn" when I finish writing the query.

example:
searchDelay: const Duration (milliseconds: 600),

@lcuis lcuis self-assigned this Dec 11, 2021
@lcuis lcuis added the enhancement New feature or request label Dec 11, 2021
@lcuis
Copy link
Owner

lcuis commented Dec 11, 2021

Hello @rhernandez-itemsoft ,

Indeed, this is a missing feature. I'm working on it.

lcuis added a commit that referenced this issue Dec 11, 2021
Added searchDelay to give some time before search function is called in Future and non-Future cases. Thanks @rhernandez-itemsoft #58
Also moved web demo to pages.
lcuis added a commit that referenced this issue Dec 11, 2021
Added searchDelay to give some time before search function is called in Future and non-Future cases. Thanks @rhernandez-itemsoft #58
Also moved web demo to pages.
lcuis added a commit that referenced this issue Dec 11, 2021
Added searchDelay to give some time before search function is called in Future and non-Future cases. Thanks @rhernandez-itemsoft #58
Also moved web demo to pages.
lcuis added a commit that referenced this issue Dec 11, 2021
Added searchDelay to give some time before search function is called in Future and non-Future cases. Thanks @rhernandez-itemsoft #58
Also moved web demo to pages.
lcuis added a commit that referenced this issue Dec 11, 2021
Added searchDelay to give some time before search function is called in Future and non-Future cases. Thanks @rhernandez-itemsoft #58
Also moved web demo to pages.
@lcuis
Copy link
Owner

lcuis commented Dec 11, 2021

Hello @rhernandez-itemsoft ,

Version 2.0.16 of the search_choices plugin now supports the new parameter searchDelay which is the delay in milliseconds applied before calling the search function. This works in Future and non-Future cases.

The search function is not called in case a new search is initiated during the delay which reduces the calls to the search function and thus, potentially, the calls to network resources.

Here are the examples from the readme:

Non-Future example

Single dialog paged delayed

SearchChoices.single(
            items: items,
            value: selectedValueSingleDialogPaged,
            hint: "Select one",
            searchHint: "Search one",
            onChanged: (value) {
              setState(() {
                selectedValueSingleDialogPaged = value;
              });
            },
            isExpanded: true,
            itemsPerPage: 5,
            currentPage: currentPage,
            searchDelay: 500,
          )

Future example

Single dialog paged future delayed

SearchChoices.single(
            value: selectedValueSingleDialogPagedFuture,
            hint: kIsWeb ? "Example not for web" : "Select one capital",
            searchHint: "Search capitals",
            onChanged: kIsWeb
                ? null
                : (value) {
                    setState(() {
                      selectedValueSingleDialogPagedFuture = value;
                    });
                  },
            isExpanded: true,
            itemsPerPage: 10,
            currentPage: currentPage,
            selectedValueWidgetFn: (item) {
              return (Center(
                  child: Card(
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(4),
                        side: BorderSide(
                          color: Colors.grey,
                          width: 1,
                        ),
                      ),
                      margin: EdgeInsets.all(1),
                      child: Padding(
                        padding: const EdgeInsets.all(6),
                        child: Text(item["capital"]),
                      ))));
            },
            futureSearchFn: (String? keyword, String? orderBy, bool? orderAsc,
                List<Tuple2<String, String>>? filters, int? pageNb) async {
              print("searching for ${keyword ?? ""}");
              String filtersString = "";
              int i = 1;
              filters?.forEach((element) {
                filtersString += "&filter" +
                    i.toString() +
                    "=" +
                    element.item1 +
                    "," +
                    element.item2;
                i++;
              });
              Response response = await get(Uri.parse(
                      "https://searchchoices.jod.li/exampleList.php?page=${pageNb ?? 1},10${orderBy == null ? "" : "&order=" + orderBy + "," + (orderAsc ?? true ? "asc" : "desc")}${(keyword == null || keyword.isEmpty) ? "" : "&filter=capital,cs," + keyword}$filtersString"))
                  .timeout(Duration(
                seconds: 10,
              ));
              if (response.statusCode != 200) {
                throw Exception("failed to get data from internet");
              }
              dynamic data = jsonDecode(response.body);
              int nbResults = data["results"];
              List<DropdownMenuItem> results = (data["records"] as List<dynamic>)
                  .map<DropdownMenuItem>((item) => DropdownMenuItem(
                        value: item,
                        child: Card(
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(4),
                            side: BorderSide(
                              color: Colors.blue,
                              width: 1,
                            ),
                          ),
                          margin: EdgeInsets.all(10),
                          child: Padding(
                            padding: const EdgeInsets.all(6),
                            child: Text(
                                "${item["capital"]} - ${item["country"]} - ${item["continent"]} - pop.: ${item["population"]}"),
                          ),
                        ),
                      ))
                  .toList();
              return (Tuple2<List<DropdownMenuItem>, int>(results, nbResults));
            },
            futureSearchOrderOptions: {
              "country": {
                "icon": Wrap(children: [
                  Icon(Icons.flag),
                  Text(
                    "Country",
                  )
                ]),
                "asc": true
              },
              "capital": {
                "icon":
                    Wrap(children: [Icon(Icons.location_city), Text("Capital")]),
                "asc": true
              },
              "continent": {"icon": "Continent", "asc": true},
              "population": {
                "icon": Wrap(children: [Icon(Icons.people), Text("Population")]),
                "asc": false
              },
            },
            futureSearchFilterOptions: {
              "continent": {
                "icon": Text("Continent"),
                "exclusive": true,
                "values": [
                  {"eq,Africa": "Africa"},
                  {"eq,Americas": "Americas"},
                  {"eq,Asia": "Asia"},
                  {"eq,Australia": "Australia"},
                  {"eq,Europe": "Europe"},
                  {"eq,Oceania": "Oceania"}
                ]
              },
              "population": {
                "icon": Wrap(children: [Icon(Icons.people), Text("Population")]),
                "exclusive": true,
                "values": [
                  {
                    "lt,1000": Wrap(children: [Icon(Icons.person), Text("<1,000")])
                  },
                  {
                    "lt,100000":
                        Wrap(children: [Icon(Icons.person_add), Text("<100,000")])
                  },
                  {
                    "lt,1000000": Wrap(
                        children: [Icon(Icons.nature_people), Text("<1,000,000")])
                  },
                  {
                    "gt,1000000":
                        Wrap(children: [Icon(Icons.people), Text(">1,000,000")])
                  },
                  {
                    "gt,10000000": Wrap(
                        children: [Icon(Icons.location_city), Text(">10,000,000")])
                  },
                ],
              },
            },
            closeButton: (selectedItemsDone, doneContext) {
              return Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  SizedBox(
                    height: 25,
                    width: 48,
                    child: (ElevatedButton(
                        onPressed: () {
                          Navigator.pop(doneContext);
                          setState(() {});
                        },
                        child: Icon(
                          Icons.close,
                          size: 17,
                        ))),
                  ),
                ],
              );
            },
            searchDelay: 500,
          )

I hope this works for you.

@rhernandez-itemsoft
Copy link
Author

thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants