[英]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.