Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to debounce Textfield onChange in Dart?

I'm trying to develop a TextField that update the data on a Firestore database when they change. It seems to work but I need to prevent the onChange event to fire multiple times.

In JS I would use lodash _debounce() but in Dart I don't know how to do it. I've read of some debounce libraries but I can't figure out how they work.

That's my code, it's only a test so something may be strange:

import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart';   class ClientePage extends StatefulWidget {    String idCliente;     ClientePage(this.idCliente);    @override   _ClientePageState createState() => new _ClientePageState();     }  class _ClientePageState extends State<ClientePage> {    TextEditingController nomeTextController = new TextEditingController();     void initState() {     super.initState();      // Start listening to changes      nomeTextController.addListener(((){         _updateNomeCliente(); // <- Prevent this function from run multiple times     }));   }     _updateNomeCliente = (){      print("Aggiorno nome cliente");     Firestore.instance.collection('clienti').document(widget.idCliente).setData( {       "nome" : nomeTextController.text     }, merge: true);    }      @override   Widget build(BuildContext context) {      return new StreamBuilder<DocumentSnapshot>(       stream: Firestore.instance.collection('clienti').document(widget.idCliente).snapshots(),       builder: (BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {         if (!snapshot.hasData) return new Text('Loading...');          nomeTextController.text = snapshot.data['nome'];           return new DefaultTabController(           length: 3,           child: new Scaffold(             body: new TabBarView(               children: <Widget>[                 new Column(                   children: <Widget>[                     new Padding(                       padding: new EdgeInsets.symmetric(                         vertical : 20.00                       ),                       child: new Container(                         child: new Row(                           mainAxisAlignment: MainAxisAlignment.spaceEvenly,                           children: <Widget>[                             new Text(snapshot.data['cognome']),                             new Text(snapshot.data['ragionesociale']),                           ],                         ),                       ),                     ),                     new Expanded(                       child: new Container(                         decoration: new BoxDecoration(                           borderRadius: BorderRadius.only(                             topLeft: Radius.circular(20.00),                             topRight: Radius.circular(20.00)                           ),                           color: Colors.brown,                         ),                         child: new ListView(                           children: <Widget>[                             new ListTile(                               title: new TextField(                                 style: new TextStyle(                                   color: Colors.white70                                 ),                                 controller: nomeTextController,                                 decoration: new InputDecoration(labelText: "Nome")                               ),                             )                           ]                         )                       ),                     )                   ],                 ),                 new Text("La seconda pagina"),                 new Text("La terza pagina"),               ]             ),             appBar: new AppBar(               title: Text(snapshot.data['nome'] + ' oh ' + snapshot.data['cognome']),               bottom: new TabBar(                           tabs: <Widget>[                   new Tab(text: "Informazioni"),  // 1st Tab                   new Tab(text: "Schede cliente"), // 2nd Tab                   new Tab(text: "Altro"), // 3rd Tab                 ],               ),             ),           )         );                },     );      print("Il widget id è");     print(widget.idCliente);        } } 
like image 835
DxW Avatar asked Aug 10 '18 17:08

DxW


People also ask

What is input debounce?

In JavaScript, a debounce function makes sure that your code is only triggered once per user input. Search box suggestions, text-field auto-saves, and eliminating double-button clicks are all use cases for debounce. In this tutorial, we'll learn how to create a debounce function in JavaScript.

What does debounce mean?

(electronics) To remove the small ripple of current that forms when a mechanical switch is pushed in an electrical circuit and makes a series of short contacts.


1 Answers

Implementation

Import dependencies:

import 'dart:async'; 

In your widget state declare a timer:

Timer? _debounce; 

Add a listener method:

_onSearchChanged(String query) {     if (_debounce?.isActive ?? false) _debounce.cancel();     _debounce = Timer(const Duration(milliseconds: 500), () {         // do something with query     });     } 

Don't forget to clean up:

@override void dispose() {     _debounce?.cancel();     super.dispose(); } 

Usage

In your build tree hook the onChanged event:

child: TextField(         onChanged: _onSearchChanged,         // ...     ) 
like image 57
Jannie Theunissen Avatar answered Oct 11 '22 14:10

Jannie Theunissen