skip to Main Content

I am trying to pass a value (the current index number of my ListView.builder) to another function. However I get the following error:

════════ Exception caught by widgets library ═══════════════════════════════════ The following RangeError was thrown building BookFeederSearch(dirty, dependencies: [_InheritedProviderScope<UserProvider?>], state: BookFeederSearchState#3217f): RangeError (index): Invalid value: Valid value range is empty: 0

Please see my code:

class Search2 extends StatefulWidget {
  static const String id = 'Search2';
  const Search2({super.key});

  @override
  State<Search2> createState() => _Search2State();
}

class _Search2State extends State<Search2> {
  bool _addToLibrary = false;


  List _allResults = [];
  List _resultList = [];

  final TextEditingController _searchController = TextEditingController();

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

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

  searchResultList() {
    var showResults = [];
    if (_searchController.text != "") {
      for (var clientSnapShot in _allResults) {
        var name = clientSnapShot['TitleEnglish'].toString().toLowerCase();
        if (name.contains(_searchController.text.toLowerCase())) {
          showResults.add(clientSnapShot);
        }
      }
    } else {
      showResults = List.from(_allResults);
    }
    setState(() {
      _resultList = showResults;
    });
  }

  getClientStream() async {
    var data = await FirebaseFirestore.instance
        .collection('Books')
        .orderBy('TitleEnglish')
        .get();
    setState(() {
      _allResults = data.docs;
    });
    searchResultList();
  }

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

  @override
  void didChangeDependencies() {
    getClientStream();
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    final User? user = Provider.of<UserProvider>(context).getUser;
    return Scaffold(
      appBar: AppBar(
        leadingWidth: 120,
        backgroundColor: const Color(
          (0XFF293D63),
        ),
        leading: IconButton(
          onPressed: () {
            //print('Go Back Pressed');
            Navigator.pop(context);
          },
          icon: SvgPicture.asset('images/button_goback_clean_svg.svg'),
        ),
        title: const Text(
          'SEARCH',
          style: TextStyle(
            fontFamily: 'Sigmar',
            fontSize: 20.0,
          ),
        ),
        centerTitle: true,
      ),
      //below links to history_book.dart
      //SingleChildScrollView avoids keyboard overflow
      body: Column(
        // crossAxisAlignment: CrossAxisAlignment.center,
        // mainAxisSize: MainAxisSize.max,
        // mainAxisAlignment: MainAxisAlignment.end,
        children: [
          Container(
            height: 50,
            width: 500,
            padding: const EdgeInsets.symmetric(horizontal: 20),
            decoration: BoxDecoration(
              // color: Color(0xFF5F94AF),
              color: Colors.blue[100],
              // border: Border.all(width: 10, color: Colors.white),

              borderRadius: const BorderRadius.only(
                bottomLeft: Radius.circular(30.0),
                bottomRight: Radius.circular(30.0),
              ),
            ),
            child: CupertinoSearchTextField(
              //done with opacity so it has no colour
              backgroundColor: Colors.white.withOpacity(0),
              controller: _searchController,
              placeholder: 'Search for book title',

              style: const TextStyle(
                fontFamily: 'NotoBold',
                fontSize: 15.0,
                color: Color((0XFF293D63)),
              ),
            ),
          ),
          Expanded(
            child: ListView.builder(
              //scrollDirection: Axis.horizontal,
              itemCount: _resultList.length,
              itemBuilder: ((context, index) {
                return Align(
                  alignment: Alignment.topCenter,
                  // this will have the folders overlap each other (set to 0.5)
                  heightFactor: 0.2,
                  child: Column(
                    children: [
                      Container(
                        height: 20,
                      ),
                      Row(
                        children: [
                          Container(
                            width: 200,
                          ),
                          Container(
                            width: 400,
                            height: 40,
                            decoration: BoxDecoration(
                              // color: Color(0xFF5F94AF),
                              color: Colors.blue[100],
                              // border: Border.all(width: 10, color: Colors.white),

                              borderRadius: const BorderRadius.only(
                                topLeft: Radius.circular(30.0),
                                topRight: Radius.circular(30.0),
                              ),
                            ),
                            alignment: Alignment.centerLeft,
                            padding: EdgeInsets.fromLTRB(20, 0, 20, 0),
                            child: InkWell(
                              onTap: () {
                                //To navigate to the next page (shows folder) and pass in the index numbers
                                final indexPage = index;
                                print('$indexPage, Open Folder');

                                Navigator.of(context).push(
                                  MaterialPageRoute(
                                    builder: (context) =>
                                        BookFeederSearch(indexPage),
                                  ),
                                );
                              },

I am unable to figure out what seems to cause this problem. I have checked by printing values, but it does get the correct input. I have passed values to other classes before without an issue but not while in a ListView.builder. So I am guessing this is causing the problem, but cannot find the solution. Much appreciated for your help.

2

Answers


  1. The error you’re encountering might be due to the way you’re passing the index value to the BookFeederSearch constructor. The BuildContext context variable should not be directly accessed inside the itemBuilder of the ListView.builder. Instead, you can use a Builder widget to create a new BuildContext within the itemBuilder.

    Here’s how you can modify your code to avoid the issue:

    ListView.builder(
      itemCount: _resultList.length,
      itemBuilder: (context, index) {
        return Builder(
          builder: (innerContext) {
            return Align(
              // ... rest of your code ...
              InkWell(
                onTap: () {
                  final indexPage = index;
                  print('$indexPage, Open Folder');
    
                  Navigator.of(innerContext).push(
                    MaterialPageRoute(
                      builder: (context) => BookFeederSearch(indexPage),
                    ),
                  );
                },
                // ... rest of your code ...
              ),
            );
          },
        );
      },
    )
    

    By using the Builder widget, you create a new BuildContext within the itemBuilder, which should resolve the issue you’re facing. Make sure to use the innerContext when navigating to the BookFeederSearch screen.

    Login or Signup to reply.
  2. The error message indicates that the valid value range is empty, meaning the index value you are passing is out of range.

    The reason might be that you are not providing a key to the BookFeederSearch widget when pushing the route using Navigator.of(context).push.

    Try to update the onTap handler to pass the index as a key to the BookFeederSearch widget:

    import 'package:flutter/foundation.dart';
    //...
    child: InkWell(
      onTap: () {
        final indexPage = index;
        print('$indexPage, Open Folder');
    
        Navigator.of(context).push(
          MaterialPageRoute(
            builder: (context) =>
                BookFeederSearch(key: ValueKey<int>(index), indexPage: indexPage),
          ),
        );
      },
      // Rest of your code...
    

    Update also the BookFeederSearch widget to receive the indexPage parameter:

    class BookFeederSearch extends StatefulWidget {
      // Add the 'indexPage' parameter to the constructor
      final int indexPage;
      BookFeederSearch({Key? key, required this.indexPage}) : super(key: key);
      //...
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search