Hi,
Today, I will show you how you can implement AutoComplete TextField in Flutter.
Watch Demo
Watch Video Tutorial
Add Library
You can get the Flutter AutoCompleteTextField Library from below link
https://pub.dartlang.org/packages/autocomplete_textfield
Get the package name and add it in the pubspec.yaml file add the dependency. We will also add the http library for the service calls we are going to make.
dependencies: flutter: sdk: flutter ..... http: "0.11.3+17" autocomplete_textfield: ^1.6.4 ...
Get the Data for AutoComplete.
We will be getting the data for showing in the Autocomplete from below url.
https://jsonplaceholder.typicode.com/users
This will return a list of users in JSON format. We will consume the data, parse it and show it in our AutoComplete TextField.
Model Class
We are going to create a model class for the Users coming from the Service.
For this example, I am using only the id, name and email for each user from the service.
Create a new file named “user.dart”. Create a class User and create the Constructor.
We will have one more method to parse a user json object and map it to a User Object.
Let’s create the class and it’s methods.
user.dart
class User { int id; String name; String email; User({this.id, this.name, this.email}); factory User.fromJson(Map<String, dynamic> parsedJson) { return User( id: parsedJson["id"], name: parsedJson["name"] as String, email: parsedJson["email"] as String, ); } }
Call the Service
I am going to write a method getUsers() that fetches the users from the Service and load the user list.
The below two methods does that. This goes to our mail file.
void getUsers() async { try { final response = await http.get("https://jsonplaceholder.typicode.com/users"); if (response.statusCode == 200) { users = loadUsers(response.body); print('Users: ${users.length}'); setState(() { loading = false; }); } else { print("Error getting users."); } } catch (e) { print("Error getting users."); } } static List<User> loadUsers(String jsonString) { final parsed = json.decode(jsonString).cast<Map<String, dynamic>>(); return parsed.map<User>((json) => User.fromJson(json)).toList(); }
Once this service executes, we will get the list of users.
Row for AutoCompleteTextField
Write a method to return the view for each row of the AutoComplete TextField.
Widget row(User user) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text( user.name, style: TextStyle(fontSize: 16.0), ), SizedBox( width: 10.0, ), Text( user.email, ), ], ); }
Build the UI
Let’s write the UI that has the AutoCompleteTextField.
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ loading ? CircularProgressIndicator() : searchTextField = AutoCompleteTextField<User>( key: key, clearOnSubmit: false, suggestions: users, style: TextStyle(color: Colors.black, fontSize: 16.0), decoration: InputDecoration( contentPadding: EdgeInsets.fromLTRB(10.0, 30.0, 10.0, 20.0), hintText: "Search Name", hintStyle: TextStyle(color: Colors.black), ), itemFilter: (item, query) { return item.name .toLowerCase() .startsWith(query.toLowerCase()); }, itemSorter: (a, b) { return a.name.compareTo(b.name); }, itemSubmitted: (item) { setState(() { searchTextField.textField.controller.text = item.name; }); }, itemBuilder: (context, item) { // ui for the autocomplete row return row(item); }, ), ], ), ); }
itemBuilder : Returns view for each row.
itemSubmitted: Returns when user submits the query.
itemFilter: Filters the user query from the list of users.
itemSorter: Compares each values in the list and sort.
Here we are using some variables that needs to be declared
1. loading : show loading until the service finishes.
2. searchTextField: Handle for AutoCompleteTextField.
3. key: Global Key for the AutoCompleteTextField.
Declarations
AutoCompleteTextField searchTextField; GlobalKey<AutoCompleteTextFieldState<User>> key = new GlobalKey(); static List<User> users = new List<User>(); bool loading = true;
Complete Example
import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'user.dart'; import 'dart:convert'; import 'package:autocomplete_textfield/autocomplete_textfield.dart'; class AutoCompleteDemo extends StatefulWidget { AutoCompleteDemo() : super(); final String title = "AutoComplete Demo"; @override _AutoCompleteDemoState createState() => _AutoCompleteDemoState(); } class _AutoCompleteDemoState extends State<AutoCompleteDemo> { AutoCompleteTextField searchTextField; GlobalKey<AutoCompleteTextFieldState<User>> key = new GlobalKey(); static List<User> users = new List<User>(); bool loading = true; void getUsers() async { try { final response = await http.get("https://jsonplaceholder.typicode.com/users"); if (response.statusCode == 200) { users = loadUsers(response.body); print('Users: ${users.length}'); setState(() { loading = false; }); } else { print("Error getting users."); } } catch (e) { print("Error getting users."); } } static List<User> loadUsers(String jsonString) { final parsed = json.decode(jsonString).cast<Map<String, dynamic>>(); return parsed.map<User>((json) => User.fromJson(json)).toList(); } @override void initState() { getUsers(); super.initState(); } Widget row(User user) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Text( user.name, style: TextStyle(fontSize: 16.0), ), SizedBox( width: 10.0, ), Text( user.email, ), ], ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Column( mainAxisAlignment: MainAxisAlignment.start, children: <Widget>[ loading ? CircularProgressIndicator() : searchTextField = AutoCompleteTextField<User>( key: key, clearOnSubmit: false, suggestions: users, style: TextStyle(color: Colors.black, fontSize: 16.0), decoration: InputDecoration( contentPadding: EdgeInsets.fromLTRB(10.0, 30.0, 10.0, 20.0), hintText: "Search Name", hintStyle: TextStyle(color: Colors.black), ), itemFilter: (item, query) { return item.name .toLowerCase() .startsWith(query.toLowerCase()); }, itemSorter: (a, b) { return a.name.compareTo(b.name); }, itemSubmitted: (item) { setState(() { searchTextField.textField.controller.text = item.name; }); }, itemBuilder: (context, item) { // ui for the autocompelete row return row(item); }, ), ], ), ); } }
All Done.
Please leave your valuable comments below.
Nice and well understandable tutorial…
But i need to know ,How to clear the previously selected date.. After submit the form, if i am opening the screen, its showing the previously selected value
Call
setState(() {
searchTextField.textField.controller.text = ”;
});