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); } }
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.
(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.
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(); }
In your build tree hook the onChanged
event:
child: TextField( onChanged: _onSearchChanged, // ... )
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With