Home > Software engineering >  Flutter: How to search from FutureBuilder Listview
Flutter: How to search from FutureBuilder Listview

Time:11-20

I am new to flutter and trying to finish the last remaining part of my app. I am using Firebase realtime database to store out employee data and listing it using a ListView.builder. I am able to show all the information in the list but I want to implement the search bar. I started off and have it in a controller and shows in the terminal but not sure how to implement it properly to filter the data.

I will past my full code but remove the firebase database as it is open right now for testing.

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'dart:async';
import 'directory_details_screen.dart';

class Directory extends StatefulWidget {
  // const ({Key? key}) : super(key: key);

  @override
  _DirectoryState createState() => _DirectoryState();
}

class _DirectoryState extends State<Directory> {
  TextEditingController _searchController = TextEditingController();

  Future getEmpData() async {
    var response = await http.get(Uri.parse(
        'FIREBASE REMOVED'));
    var jsonData = jsonDecode(response.body);
    List<Employee> employees = [];

    for (var e in jsonData) {
      Employee employee = Employee(
          e["displayName"],
          e["department"],
          e["jobTitle"],
          e["mobilePhone"],
          e["workEmail"],
          e["photoUrl"],
          e["workPhoneExtension"]);
      employees.add(employee);
    }
    print(employees.length);
    return employees;
  }


  @override
  void initState() {
    super.initState();
    _searchController.addListener(_onSearchChanged);
  }

  @override
  void dispose() {
    _searchController.removeListener(_onSearchChanged);
    _searchController.dispose();
    super.dispose();
  }

  _onSearchChanged() {
    print(_searchController.text);
  }

  String searchString = "";

  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(height: 10),
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 15.0),
            child: TextField(
              onChanged: (value) {
                setState(() {
                  searchString = value;
                });
              },
              controller: _searchController,
              decoration: InputDecoration(
                labelText: 'Search',
                suffixIcon: Icon(Icons.search),
              ),
            ),
          ),
          SizedBox(height: 10),
          Expanded(
            child: FutureBuilder(
              future: getEmpData(),
              builder: (context, AsyncSnapshot snapshot) {
                if (snapshot.data == null) {
                  return Container(
                    child: Center(
                      child: CircularProgressIndicator(),
                    ),
                  );
                } else
                  return ListView.builder(
                      itemCount: snapshot.data!.length,
                      itemBuilder: (context, i) {
                        return Card(
                          child: ListTile(
                            leading: CircleAvatar(
                              backgroundImage: NetworkImage(
                                snapshot.data[i].photoUrl
                              ),
                            ),
                            //leading: Icon(Icons.account_circle),
                            isThreeLine: true,
                            title: Text(snapshot.data[i].displayName,
                                style: TextStyle(fontWeight: FontWeight.bold)),
                            subtitle: Text("Department: "  
                                snapshot.data[i].department  
                                "\n"  
                                "Title: "  
                                snapshot.data[i].jobTitle),
                            onTap: () {
                              Navigator.of(context).push(MaterialPageRoute(
                                  builder: (context) => EmployeeDetails(
                                      employee: snapshot.data[i])));
                            },
                          ),
                        );
                      });
              },
            ),
          ),
        ],
      ),
    );
  }
}

class Employee {
  final String displayName,
      department,
      jobTitle,
      mobilePhone,
      workEmail,
      photoUrl,
      workPhoneExtension;
  Employee(this.displayName, this.department, this.jobTitle, this.mobilePhone,
      this.workEmail, this.photoUrl, this.workPhoneExtension);
}
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You can try something like this:

...
} else {
final result = _search(snapshot.data);

  return ListView.builder(
      itemCount: result.length,
      itemBuilder: (context, i) {
        return Card(
          child: ListTile(
            leading: CircleAvatar(
              backgroundImage: NetworkImage(
                  result[i].photoUrl
              ),
            ),
            //leading: Icon(Icons.account_circle),
            isThreeLine: true,
            title: Text(result[i].displayName,
                style: TextStyle(fontWeight: FontWeight.bold)),
            subtitle: Text("Department: "  
                result[i].department  
                "\n"  
                "Title: "  
                result[i].jobTitle),
            onTap: () {
              Navigator.of(context).push(MaterialPageRoute(
                  builder: (context) =>
                      EmployeeDetails(
                          employee: result[i])));
            },
          ),
        );
      });
    ...

and search method like

List<Employee> _search(List<Employee>? employee) {
  if(searchString?.isNotEmpty == true) {
    //search logic what you want
    return employee?.where((element) => element.department.contains(searchString))
        .toList() ?? <Employee>[];
  }
  
  return employee ?? <Employee>[];
}
  • Related