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