Flutter Tutorials – AutoComplete TextField

By | January 11, 2019

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.

2 thoughts on “Flutter Tutorials – AutoComplete TextField

  1. Faizal

    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

    Reply
    1. James Post author

      Call
      setState(() {
      searchTextField.textField.controller.text = ”;
      });

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *