Home > Mobile >  Create a search function which filter data from a REST API
Create a search function which filter data from a REST API

Time:10-25

I am currently trying to create a search function to filter a constitution on the Home Page by using the name[title]. I used the CupertinoSearchTextField class. The constitutions posted will be displayed when the homepage, the search bar will allow users to search for a specific constitution.

Code of search widget container

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class SearchBar extends StatelessWidget {
  const SearchBar({super.key});


  @override
  Widget build(BuildContext context) {
    return Container(
                    margin: const EdgeInsets.symmetric(vertical: 30),
                    padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 8),
                    child: CupertinoSearchTextField(
                      onChanged: ((value) {
                        
                      }),
                      autofocus: true,
                      itemColor: Colors.black,
                      itemSize: 20,
                      backgroundColor: const Color.fromARGB(255, 185, 204, 218),
                      placeholderStyle: const TextStyle(
                        color: Colors.black,
                        fontSize: 18,
                      ),
                    ),
                  );
  }
}

Code of the Home Page

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:project/controller/constitution_controller.dart';
import 'package:project/model/constitution_model.dart';
import 'package:project/screens/branch_page.dart';
import 'package:project/widgets/drawer_widget.dart';
import 'package:project/widgets/searchbar.dart';
import 'package:project/widgets/shimmer_grid_card.dart';
import 'package:shimmer/shimmer.dart';

import '../widgets/constitution_card.dart';

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
 

  final ConstitutionController constitutionController = Get.find();

  @override
  Widget build(BuildContext context) {
    final double height = MediaQuery.of(context).size.height;

    return Scaffold(
      appBar: AppBar(
        backgroundColor: const Color(0xFF0B3C5D),
        elevation: 0.0,
      ),
      drawer: DrawerWidget(),
      body: Stack(children: [
        Container(
          height: height * 0.45,
          decoration: const BoxDecoration(
            color: Color(0xFF0B3C5D),
            // image: DecorationImage(
            //   image: ExactAssetImage('images/hpb.png'))
          ),
        ),
        SafeArea(
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 20),
            child: Column(
              children: [
                Text(
                  'Legal Companion',
                  style: GoogleFonts.firaSans(
                    textStyle: const TextStyle(
                      color: Colors.white,
                      fontSize: 32,
                    ),
                  ),
                ),
                // The Search bar
                const SearchBar(),

                
                const SizedBox(
                  height: 70,
                ),
                Flexible(
                  child: Obx(() {
                    if (constitutionController.isLoading.value) {
                      return GridView.builder(
                        itemBuilder: (_, __) {
                          return Shimmer.fromColors(
                              baseColor: Colors.grey[300]!,
                              highlightColor: Colors.grey[100]!,
                              period: Duration(seconds: 2),
                              enabled: constitutionController.isLoading.value,
                              child: ShimmerGridCard());
                        },
                        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                            crossAxisCount: 2),
                      );
                    } else {
                      return GridView.builder(
                          itemCount:
                              constitutionController.constitutionList.length,
                          gridDelegate:
                              SliverGridDelegateWithFixedCrossAxisCount(
                                  crossAxisCount: 2),
                          itemBuilder: (context, index) {
                            Constitution constitution =
                                constitutionController.constitutionList[index];
                            return InkWell(
                                onTap: (() {
                                  Get.to(
                                      BranchPage(constitutionId: constitution));
                                }),
                                child: ConstitutionCard(constitutionController
                                    .constitutionList[index]));
                          });
                    }
                  }),
                ),
              ],
            ),
          ),
        ),
      ]),
    );
  }
}

The Constitution Card Code. The various cards on the home page

// ignore_for_file: prefer_const_constructors

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:project/model/constitution_model.dart';

class ConstitutionCard extends StatelessWidget {
  final Constitution constitution;
  const ConstitutionCard(this.constitution, {super.key});

  
  @override
  Widget build(BuildContext context) {
    return Card(
      color: Colors.blueAccent[80],
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Spacer(),
            SizedBox(
              height: 85,
              width: double.infinity,
              child: SvgPicture.asset("assets/images/ug.svg"),
            ),
            const Spacer(),
            Text(
              constitution.title,
              textAlign: TextAlign.center,
              style: GoogleFonts.openSans(
                textStyle: const TextStyle(
                fontSize: 16,
                fontWeight: FontWeight.w700,
              ),
            ),
          ),
          Spacer()
        ],
        ),
      ),
    );
  }
}

The Code of the Controller

import 'dart:convert';

import 'package:get/state_manager.dart';
import 'package:project/model/constitution_model.dart';
import 'package:project/services/service.dart';

class ConstitutionController extends GetxController {
  var isLoading = false.obs;
  RxList constitutionList = <Constitution>[].obs;
  RxList chapterList = <Chapter>[].obs;
  RxList sectionList = <Section>[].obs;

//Causes the objects to appear on debugging
  @override
  void onInit() {
    getConstitutions("");
    super.onInit();
  }


  void getConstitutions(String search) async {
    try {
      isLoading(true);

      dynamic response = await HttpService.getConstitutions(search);

      if (response.statusCode == 200) {
        List<dynamic> body = jsonDecode(response.body);

        List<Constitution> constitutions = body
            .map(
              (dynamic item) => Constitution.fromJson(item),
            )
            .toList();

        constitutionList(constitutions);

        isLoading(false);
      }
    } catch (err) {
      isLoading(false);
    } finally {
      isLoading(false);
    }
  }

  Future getChapters(String constitutionId) async {
    try {
      isLoading(true);

      dynamic response = await HttpService.getChapters(constitutionId);

      if (response.statusCode == 200) {
        List<dynamic> body = jsonDecode(response.body);

        List<Chapter> chapters = body
            .map(
              (dynamic item) => Chapter.fromJson(item),
            )
            .toList();

        chapterList(chapters);

        isLoading(false);
      }
    } catch (err) {
      // print(err);
      isLoading(false);
    } finally {
      isLoading(false);
    }
  }

  Future getSections(String constitutionId, String chapterId) async {
    try {
      isLoading(true);
      dynamic response =
          await HttpService.getSections(constitutionId, chapterId);

      if (response.statusCode == 200) {
        List<dynamic> body = jsonDecode(response.body);

        List<Section> sections = body
            .map(
              (dynamic item) => Section.fromJson(item),
            )
            .toList();

        sectionList(sections);

        // print(sectionList);

        isLoading(false);
      }
    } catch (err) {
      // print("errorr hhhherrrrrrrhhhh");
      // print(err);
      isLoading(false);
    }
    finally {
      isLoading(false);
    }
  }
}

CodePudding user response:

As far as I can understand, you are trying to achieve something like below listview search.

enter image description here

If yes, then You have to use some state management, so that you can handle the loading, and filtering state handling. You can use BloC, valueListenableBuilder, or something like that.

E.g. ValueListenableBuilder https://blog.devgenius.io/flutter-valuenotifier-and-valuelistenablebuilder-41c700315786

In your case, you have to notify in onChange callback of CupertinoSearchTextField.

CodePudding user response:

    import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';

class SearchBarWidget extends StatefulWidget {
  const SearchBarWidget({super.key});

  @override
  State<SearchBarWidget> createState() => _SearchBarWidgetState();
}

class _SearchBarWidgetState extends State<SearchBarWidget> {
  List<String> list = ["Arshad", "khan", "junaid", "Babar", "Tariq", "Mobile"];
  String search = "";
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TextField(
          onChanged: (value) {
            setState(() {
              search = value;
            });
          },
        ),
      ),
      body: ListView.builder(
        itemCount: list.length,
        itemBuilder: (context, index) {
          if (search.isEmpty) {
            return ListTile(
              title: Text(list[index]),
            );
          }
          if (list[index].toLowerCase().contains(search)) {
            return ListTile(
              title: Text(list[index]),
            );
          }
          return Container();
        },
      ),
    );
  }
}

Note: This is easy method

  • Related