Tutorial Flutter Cara Membuat Autocomplete Search

Tutorial flutter autocomplete search
Tutorial flutter autocomplete search
Codingtive.com - Halo teman-teman, akhirnya codingtive update kembali setelah beberapa bulan jarang update tutorial. Pada kesempatan ini, codingtive akan berbagi codelab cara membuat pencarian autocomplete dengan Flutter. Sebelumnya, udah tau yang dimaksud autocomplete belum ?

Jadi, pencarian dengan autocomplete yaitu ketika pengguna mengetik di form pencarian, maka akan muncul suggestion yang berkaitan dengan kata kuncinya. Nah, menarik bukan ? Yuk langsung saja pelajari dan praktekan codelabnya.

Illustrasi latihan

Membuat halaman yang terdapat form pencarian, pengguna dapat mencari nama klub sepak bola dan menampilkan hasil yang relevan dengan kata kunci, serta mengambil data dari klub yang dipilih. Hasilnya seperti berikut :
codelab flutter autocomplete
codelab flutter autocomplete

Codelab

Pertama, siapkan terlebih dahulu project Flutter baru atau menggunakan yang sudah ada.

Menambahkan dependencies

Tambahkan dependencies Flutter TypeAhead didalam file pubspec.yaml pada bagian berikut :
dependencies:
  flutter:
    sdk: flutter
  flutter_typeahead: ^1.6.1
Jangan lupa untuk update packagenya jika menggunakan terminal ketikan "flutter pub get".

Menyiapkan data json

Untuk datanya kita akan menggunakan json dari lokal, buat folder baru dengan nama assets, dan buat file didalamnya dengan nama clubs.json. Isinya kamu dapat copy paste dari clubs.json.

Jangan lupa untuk menambah permission didalam file pubspec.yaml, tambahkan kode berikut pada bagian assets :
# To add assets to your application, add an assets section, like this:
assets:
  - assets/clubs.json

Membuat class Model (POJO)

Untuk memudahkan parsing dari json, kita akan menggunakan class model untuk menampung datanya. Buat folder baru didalam folder lib, buat file baru dengan nama clubs.dart. Isinya seperti berikut :
class DataMaster {
  List<Club> clubs;

  DataMaster({this.clubs});

  DataMaster.fromJson(Map<String, dynamic> json) {
    if (json['clubs'] != null) {
      clubs = new List<Club>();
      json['clubs'].forEach((value) {
        clubs.add(new Club.fromJson(value));
      });
    }
  }
}

class Club {
  int id;
  String name;
  String code;

  Club({this.id, this.name, this.code});

  Club.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    code = json['code'];
  }
}

List<Club> getClubSuggestions(String query, List<Club> clubs) {
  List<Club> matchedClubs = new List();

  matchedClubs.addAll(clubs);
  matchedClubs.retainWhere((club) => club.name.toLowerCase().contains(query.toLowerCase()));

  if (query == '') {
    return clubs;
  } else {
    return matchedClubs;
  }
}

Membuat tampilan dan implementasi

Didalam folder lib, buatlah folder baru dengan nama ui, pindahkan file main.dart ke folder ui.

Pertama, ubah semua kodenya dan tambahkan import terlebih dahulu :
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_autocomplete_search/model/clubs.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:flutter/services.dart';
Buat fungsi main() seperti berikut :
void main() {
  runApp(MaterialApp(
    title: 'Autocomplete Search',
    debugShowCheckedModeBanner: false,
    home: MainPage(),
  ));
}
Buat class baru berupa StatefullWidget, kodenya seperti berikut :
class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  Club club = new Club();
  TextEditingController _textFieldController = new TextEditingController();

  Future<String> loadJson() async {
    return rootBundle.loadString('assets/clubs.json');
  }

  @override
  void dispose() {
    _textFieldController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold();
  }
}
Supaya lebih rapi akan kita bagi menjadi fungsi tersendiri didalam class _MainPageState, pertama buat fungsi untuk formnya seperti berikut :
Widget _buildTextField(List clubs) {
  return TypeAheadFormField(
    textFieldConfiguration: TextFieldConfiguration(
      autofocus: false,
      controller: _textFieldController,
      style: TextStyle(
        color: Colors.black54,
        fontSize: 18.0,
      ),
      keyboardType: TextInputType.text,
      decoration: InputDecoration(
        labelText: "Search Football Club",
        labelStyle: TextStyle(color: Colors.black38),
        enabledBorder: UnderlineInputBorder(
          borderSide: BorderSide(color: Colors.blueAccent),
        ),
      ),
    ),
    suggestionsCallback: (String query) {
      return getClubSuggestions(query, clubs);
    },
    onSuggestionSelected: (Club club) {
      setState(() {
        this.club = club;
      });
      _textFieldController.text = club.name;
    },
    noItemsFoundBuilder: (BuildContext context) {
      return ListTile(
        title: Text('Club not found..'),
      );
    },
    itemBuilder: (BuildContext context, Club club) {
      return ListTile(
        title: Text(club.name),
        subtitle: Text(
          'ID : ${club.id}, Code : ${club.code}',
          style: TextStyle(
            fontSize: 12.0,
            fontStyle: FontStyle.italic,
          ),
        ),
      );
    },
  );
}
Buat fungsi untuk menampilkan outputnya :
Widget _buildOutput() {
  return Text("""
  Result for club selected :
  
  ID    : ${club.id ?? '-'}
  Name  : ${club.name ?? '-'}
  Code  : ${club.code ?? '-'}"""
  );
}
Selanjutnya, buat fungsi untuk Container yang menampung form dan output :
Widget _buildContainer(List<Club> clubs) {
  return Container(
    padding: EdgeInsets.all(20.0),
    child: Center(
      child: Column(
        children: <Widget>[
          _buildTextField(clubs),
          SizedBox(height: 16.0),
          _buildOutput(),
        ],
      ),
    ),
  );
}

Parsing data dari json

Sebelumnya kita sudah membuat fungsi loadJson() yang berupa Future<String>, kita akan mengambil datanya dengan memanfaatkan widget FutureBuilder(). Caranya, didalam fungsi main() yang Scaffold masih kosong, ubah menjadi seperti berikut :
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Autocomplete Search'),
      centerTitle: true,
    ),
    body: FutureBuilder<String>(
      future: loadJson(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          final dataMaster = DataMaster.fromJson(json.decode(snapshot.data));
          return _buildContainer(dataMaster.clubs);
        } else {
          return Center(
            child: Text('Error load data'),
          );
        }
      },
    ),
  );
}
Jangan lupa untuk mengubah class didalam folder test karena belum disesuaikan, buka file widget_test.dart didalam folder test, sesuaikan nama class yang error menjadi seperti berikut :
// Build our app and trigger a frame.
await tester.pumpWidget(MainPage());
Sekarang coba jalankan dengan emulator atau device.

Full kode main.dart

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:flutter_autocomplete_search/model/clubs.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(MaterialApp(
    title: 'Autocomplete Search',
    debugShowCheckedModeBanner: false,
    home: MainPage(),
  ));
}

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  Club club = new Club();
  TextEditingController _textFieldController = new TextEditingController();

  Future<String> loadJson() async {
    return rootBundle.loadString('assets/clubs.json');
  }

  @override
  void dispose() {
    _textFieldController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Autocomplete Search'),
        centerTitle: true,
      ),
      body: FutureBuilder<String>(
        future: loadJson(),
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            final dataMaster = DataMaster.fromJson(json.decode(snapshot.data));
            return _buildContainer(dataMaster.clubs);
          } else {
            return Center(
              child: Text('Error load data'),
            );
          }
        },
      ),
    );
  }

  Widget _buildContainer(List<Club> clubs) {
    return Container(
      padding: EdgeInsets.all(20.0),
      child: Center(
        child: Column(
          children: <Widget>[
            _buildTextField(clubs),
            SizedBox(height: 16.0),
            _buildOutput(),
          ],
        ),
      ),
    );
  }

  Widget _buildTextField(List<Club> clubs) {
    return TypeAheadFormField(
      textFieldConfiguration: TextFieldConfiguration(
        autofocus: false,
        controller: _textFieldController,
        style: TextStyle(
          color: Colors.black54,
          fontSize: 18.0,
        ),
        keyboardType: TextInputType.text,
        decoration: InputDecoration(
          labelText: "Search Football Club",
          labelStyle: TextStyle(color: Colors.black38),
          enabledBorder: UnderlineInputBorder(
            borderSide: BorderSide(color: Colors.blueAccent),
          ),
        ),
      ),
      suggestionsCallback: (String query) {
        return getClubSuggestions(query, clubs);
      },
      onSuggestionSelected: (Club club) {
        setState(() {
          this.club = club;
        });
        _textFieldController.text = club.name;
      },
      noItemsFoundBuilder: (BuildContext context) {
        return ListTile(
          title: Text('Club not found..'),
        );
      },
      itemBuilder: (BuildContext context, Club club) {
        return ListTile(
          title: Text(club.name),
          subtitle: Text(
            'ID : ${club.id}, Code : ${club.code}',
            style: TextStyle(
              fontSize: 12.0,
              fontStyle: FontStyle.italic,
            ),
          ),
        );
      },
    );
  }

  Widget _buildOutput() {
    return Text("""
    Result for club selected :
    
    ID    : ${club.id ?? '-'}
    Name  : ${club.name ?? '-'}
    Code  : ${club.code ?? '-'}"""
    );
  }
}

Github

Untuk source code lengkapnya juga dapat diakses di repository github, jangan lupa star ya.

Kesimpulan

Pada codelab ini kamu sudah berhasil membuat pencarian dengan autocomplete, selanjutnya kamu dapat berkreasi dan mengembangkan lebih lanjut lagi seperti mengatur handle terhadap keyword, parsing data yang diambil dari internet, dan masih banyak lagi.

Jika kamu ada pertanyaan atau kendala, silahkan mengisi di form komentar, ikuti terus codingtive untuk codelab selanjutnya ya. Semoga bermanfaat.

Pelajari juga tutorial berikut :
Tutorial Flutter Membuat Toggle Password
Tutorial Flutter Cara Membuat Radio Button
Tutorial Flutter Cara Menggunakan Snackbar

Berlangganan update artikel terbaru via email:

Belum ada Komentar untuk "Tutorial Flutter Cara Membuat Autocomplete Search"

Posting Komentar

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel