Is there a way to send a request after the user has stopped typing?
3,429
Solution 1
you can use the below code to do this:
import 'package:flutter/material.dart';
import 'dart:async';
class Test extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _TestState();
}
}
class _TestState extends State<StatefulWidget> {
Timer searchOnStoppedTyping;
_onChangeHandler(value ) {
const duration = Duration(milliseconds:800); // set the duration that you want call search() after that.
if (searchOnStoppedTyping != null) {
setState(() => searchOnStoppedTyping.cancel()); // clear timer
}
setState(() => searchOnStoppedTyping = new Timer(duration, () => search(value)));
}
search(value) {
print('hello world from search . the value is $value');
}
@override
Widget build(BuildContext context) {
return TextField(
onChanged: _onChangeHandler,
decoration: InputDecoration(
hintText: 'Search ....'
),
);
}
}
Solution 2
The usual way to do this in Flutter is using RxDart and its debounce()
method. It allows to wait a small period before launching a specific call.
In the following full example you see it in action with a time of 1 second. In the example, a message is shown where the call to the server should be dispatched.
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final subject = new PublishSubject<String>();
bool isLoading = false;
GlobalKey<ScaffoldState> scaffoldKey = new GlobalKey();
void _textChanged(String text) {
if (text.isEmpty) {
setState(() {
isLoading = false;
});
return;
}
setState(() {
isLoading = true;
});
scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text("Search for ${text}"),
));
}
@override
void initState() {
super.initState();
subject.stream.debounce(new Duration(milliseconds: 1000)).listen(_textChanged);
}
@override
void dispose() {
subject.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return new Scaffold(
key: scaffoldKey,
appBar: new AppBar(
title: new Text("Debounce demo"),
),
body: new Container(
padding: new EdgeInsets.all(8.0),
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new TextField(
decoration: new InputDecoration(
hintText: 'Type text to search',
),
onChanged: (string) => (subject.add(string)),
),
isLoading
? Padding(
padding: const EdgeInsets.all(20.0),
child: new CircularProgressIndicator(),
)
: new Container(),
],
),
),
);
}
}
You can see this code in action in the following article and code by Norbert Kozsir
Author by
vox
Updated on December 07, 2022Comments
-
vox over 1 year
- I am looking for a way to send an API request after the user has stopped typing for X amount of seconds.
- The way I am sending the request is through the onTextChanged callback, however, that sends a request on every key press
- I have seen ways to do this with a timeout in React, however, I am relatively new to flutter so any help would be appreciated
-
tapizquent almost 5 yearsNot entirely okay as if the user changes focus before the timer has gone off, it cancels the timer and might stay in old state.
-
Isac Moura almost 4 yearsEven if your code is the right answer for this question, is a good practice to provide some explanation about the code.
-
Muhammad Faizan about 3 yearsgreat, exactly what I was looking for
-
Abhishek Thapliyal almost 3 yearsyou saved me to install rxdart or stream_transform library for this simple solution