繁体   English   中英

在 dart 中过滤具有多个下拉列表的列表

[英]filter a list with multiple dropdowns in dart

嘿,感谢您检查我的问题,我正在制作一个连接到 api 并像这样拉回 json 数据的应用程序

主屏幕 我一直在尝试让过滤系统正常工作,例如列表可以按某个系列和其他选项排序,我在代码中有两个列表,一个是来自名为 _userdetails 的 api 的所有结果,另一个是用于搜索结果称为_searchresult。

我的目标是让过滤器和搜索栏同步工作,例如,您可以过滤一个名为 onepiece 的系列,然后使用其他过滤器过滤该新列表以缩小结果范围,甚至在这些新列表上使用搜索栏列表。

目前我有过滤器在一定程度上工作,如果系列被选为龙珠,它将选择所有龙珠字符,但一旦使用新过滤器或搜索,它只会重置列表,这里是下拉列表的代码

new Row(
          mainAxisAlignment: MainAxisAlignment.start,
          mainAxisSize: MainAxisSize.max,
          crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                 // Text("Select a series"),


                new  DropdownButton<String>(
                    hint: Text("Series"),
                   // value: null,

                    items: _fieldList.map((value){
                      return DropdownMenuItem<String>(
                        value: value.series,
                        child: Container(
                          width: 100,
                        child: new Text(value.series),
                       // height: 5.0,
                          ),
                      );
                    }).toList(),
                    onChanged: (String val) {
                      _selectedText = val;
                      setState(() {
                       // _searchResult.clear();
                      //  _searchResult.removeWhere((userDetail) => userDetail.series != _selectedText);
                         // _newList.clear();
                        _selectedText = val;
                        _userDetails.forEach((userDetail) {

                          if(userDetail.series.contains(_selectedText)){
                            userDetail.remove((userDetail) => userDetail.series != _selectedText);
                            _searchResult.add(userDetail);}
                          if(_searchResult.contains(_selectedText))
                            _searchResult.removeWhere((userDetail) => userDetail.series != _selectedText);

                          //   _userDetails.where((f) => f.series.contains(_selectedText)).toList(); //apples

                          print(_searchResult.length);

                        });
                        print(_selectedText);
                      });
                    },
                  ),

                 new DropdownButton<String>(
                    hint: Text("Class"),
                    // value: null,

                    items: _fieldList.map((value){
                      return DropdownMenuItem<String>(
                        value: value.classs,
                        child: new Text(value.classs),
                      );
                    }).toList(),
                    onChanged: (String val) {
                      _selectedText = val;
                      setState(() {

                        _searchResult.removeWhere((userDetail) => userDetail.classs != _selectedText);

                        _userDetails.forEach((userDetail) {
                        if (userDetail.classs.contains(_selectedText))
                          ///loops thrpugh each user detail and add where selectedtext = whatever
                        //  _searchResult.removeWhere((_searchResult) => userDetail.classs != _selectedText);
                          _searchResult.removeWhere((userDetail) => userDetail.classs != _selectedText);

                        _searchResult.add(userDetail);
                      //  _userDetails.where((f) => f.classs.contains(_selectedText)).toList(); //apples

                       /// _searchResult.add(userDetail);

                        });

                           // _searchResult.add(userDetail);
                          print(_selectedText);
                          //_searchResult.remove(userDetail.classs.)

                          //_newList.add(userDetail);
                          print(_searchResult.length);

                       // });
                        print(_selectedText);
                      });
                    },
                  ),
                  SizedBox(
                    height: 5.0,
                  ),
                  Text('Selected: ${_selectedText}'),
                ],
              ),

这是列表视图的代码

new Expanded(
            child: _searchResult.length != 0 || controller.text.isNotEmpty
                ? new ListView.builder(
              itemCount: _searchResult.length,
              itemBuilder: (context, i) {
                return new Card(
                  child: new ListTile(
                    leading: new CircleAvatar(backgroundImage: new NetworkImage("https://ochd.co.uk/db/puti/Assets/Portraits/"+_searchResult[i].portrait,),),
                    title: new Text(_searchResult[i].name),
                    subtitle: new Text(_searchResult[i].classs),
                    onTap: () {
                      Navigator.push(context, new MaterialPageRoute(builder: (context) => DetailPage(_searchResult[i])));},
                  ),
                  margin:
                  const EdgeInsets.all(0.0),
                );
              },
            )
                : new ListView.builder(
              itemCount: _userDetails.length,
              itemBuilder: (context, index) {
                return new Card(
                  child: new ListTile(
                    leading: new CircleAvatar(backgroundImage: new NetworkImage("https://ochd.co.uk/db/puti/Assets/Portraits/"+_userDetails[index].portrait,),),
                    title: new Text(_userDetails[index].name),
                    subtitle: new Text(_userDetails[index].classs),
                    trailing: new CircleAvatar(backgroundImage: new NetworkImage("https://ochd.co.uk/db/puti/Assets/"+_userDetails[index].type,),),
                    onTap: () {
                      Navigator.push(context, new MaterialPageRoute(builder: (context) => DetailPage(_userDetails[index])));},
                  ),
                  margin: const EdgeInsets.all(0.0),
                );
              },
            ),

          ),

我有点难住哈哈

您在搜索或更改过滤器后不断重置列表的原因是您正在调用 setstate 并分配值 _selectedText = val。 您正在为 selectedText 分配一个新值。

//Excerpt from your code

onChanged: (String val) {
      setState(() {
     /// When the dropdown value changes you are assigning a new value to selected 
     /// text
     /// Assuming it had Goto and the user selected Vegeta, the new value of 
     /// selectedText will be Vegeta
     _selectedText = val;
     // The statement that follows will evaluate based on the new value 
   });
  });

我建议使用面向对象的方法并从这些字段创建模型,并使用 i、e 系列和类或使用映射而不是字符串。 如果您觉得字符串更适合具有与过滤器数量相等的字符串,即将 selectedText 转换为 Map。 由于您使用的是 DropdownMenu,我的假设是您只需要每个过滤器中的一个值

///Initialize your set outside the build method and results
final Map<String,String> selected = {"series":"","class":""}

/// Initialized the results list with the initial result set 
List results = userDetails;

/// Method to build your results

void buildResults(){
  setState((){
    var seriesList = 

/// comparing strings in dart is case sensitive so 
///  depending on your data you may consider 
/// converting all the strings you are comparing to lowercase 
 _userList
 .where((userDetail)=>userDetail
 .series
 .toLowerCase()
  .contains(selected["series"]))).toList();

  var classList = 
  _userList
  .where((userDetail)=>userDetail
  .class.toLowerCase()
  .contains(selected["class"]))).toList();
 
  /// Merge the two lists using spread operator
  /// Assuming you are using Dart > 2.3
  var list3 = [...seriesList, ...classList];

  results = list3;
 
});
}

/// onChanged method of Dropdown button
/// Assuming this is the series dropdown
setState((){
  selected.update(
   "series", 
    // if it is already in the map
   (existingValue) => value, 
   ifAbsent: () => value,
 );
buildResults();
});






 /// In your listview builder
 ListView.builder(
 itemCount: results.length, 
 itemBuilder:(context,index){
}

您可以找到更有效的方法。 你不需要我两次调用 setstate 。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM