Search code examples
flutterdartflutter-layoutflutter-textflutter-textinputfield

Screen goes blank if I search for something in TextField that is out of my list


I have created a list in another directory which is a list of JSON data and I have showed it on screen and also added a TextField which works as a search bar. it works fine if I search for a letter(or combination of letters) that is inside my list but when I search for something out of list the whole page goes blank except for the Appbar. here's my code:

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

import 'package:flutter/services.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      // Hide the debug banner
      debugShowCheckedModeBanner: false,
      title: 'Kindacode.com',
      home: HomePage(),
    );
  }
}

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

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

class _HomePageState extends State<HomePage> {
  List _items = [];
  List _itemsForDisplay = [];

  // Fetch content from the json file
  Future<void> readJson() async {
    final String response = await rootBundle.loadString('assets/Symptoms.json');
    final data = await json.decode(response);
    setState(() {
      _items = data["Symptoms"];
      _itemsForDisplay = _items;
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    readJson();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        centerTitle: true,
        title: const Text(
          'Diagnose',
        ),
      ),
      body: Padding(
        padding: const EdgeInsets.all(25),
        child: Column(
          children: [
            // Display the data loaded from sample.json

            Expanded(
              child: ListView.builder(
                itemBuilder: (context, index) {
                  return index == 0 ? _searchBar() : _ListItem(index);
                },
                itemCount: _itemsForDisplay.length,
              ),
            )
          ],
        ),
      ),
    );
  }

  _searchBar() {
    return Padding(
      padding: const EdgeInsets.all(8),
      child: TextField(
        decoration: InputDecoration(hintText: 'Search'),
        onChanged: (text) {
          text = text.toLowerCase();
          setState(() {
            _itemsForDisplay = _items.where((item) {
              var itemTitle = item.toLowerCase();
              return itemTitle.contains(text);
            }).toList();
          });
        },
      ),
    );
  }

  _ListItem(index) {
    return Card(
      margin: const EdgeInsets.all(10),
      child: ListTile(
        leading: Text(_itemsForDisplay[index]),
      ),
    );
  }
}

Here's a picture before for searching for something that is an entity of my list enter image description here

and this happens when I search for "." or anything that is not in my list: enter image description here


Solution

  • In your item builder return only _ListItem(index) and put _searchBar outside of Expanded. In current code, you are skipping first element from list and showing search bar instead, which is wrong. That's why when length of list is 0 you don't see anything. Because builder doesn't get executed.

    So, your built method should look like this:

     @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            centerTitle: true,
            title: const Text(
              'Diagnose',
            ),
          ),
          body: Padding(
            padding: const EdgeInsets.all(25),
            child: Column(
              children: [
                // Display the data loaded from sample.json
                _searchBar(),
                Expanded(
                  child: ListView.builder(
                    itemBuilder: (context, index) {
                      return _ListItem(index);
                    },
                    itemCount: _itemsForDisplay.length,
                  ),
                )
              ],
            ),
          ),
        );
      }