通过 RIverpod 的 useTextEditingController 搜索不工作
Searching via useTextEditingController of RIverpod not working
我有一个带有通过 useTextEditingController 提供的控制器的文本字段。控制器文本应该是传递给提供者控制器中的函数的值,以搜索相应的产品并显示它们。但是,没有返回任何搜索结果。我已经通过 print() 语句确认读取并假定传递的值是用户输入到文本字段中的值。对于为什么结果(proList)没有返回到回调以供显示,我束手无策。这是相关的代码片段。
请注意,我通过在查询前将搜索文本转换为小写字母来处理区分大小写问题,以确保这不会影响查询。感谢您的帮助或指点。
search_screen.dart
class SearchScreen extends HookConsumerWidget {
static const routeName = '/searchScreen';
SearchScreen({Key? key}) : super(key: key);
late List<Product> _searchList = [];
@override
Widget build(BuildContext context, WidgetRef ref) {
List<Product> prodSearchList =
ref.watch(productControllerProvider.notifier).products;
final _searchTextController = useTextEditingController();
final FocusNode _node = FocusNode();
final _isSearchFieldEmpty = useState<bool>(true);
bool isSearchFieldEmpty() {
return _searchTextController.text.isEmpty;
}
useEffect(() {
_searchTextController.addListener(() {
_isSearchFieldEmpty.value = isSearchFieldEmpty();
});
}, [_searchTextController]);
return Scaffold(
bottomSheet: TextField(
autofocus: true,
controller: _searchTextController,
focusNode: _node,
decoration: kTextInputDecoration.copyWith(
hintText: 'Item name here ...',
filled: true,
fillColor: Theme.of(context).cardColor,
prefixIcon: const Icon(Icons.search),
suffixIcon: IconButton(
onPressed: _searchTextController.text.isEmpty
? null
: () {
_searchTextController.clear();
},
icon: Icon(Icons.close,
color: _searchTextController.text.isNotEmpty
? Colors.red
: Colors.grey),
),
),
onChanged: (val) {
_searchList =
ref.watch(productControllerProvider.notifier).getBySearch(val);
},
),
body: _searchTextController.text.isNotEmpty && _searchList.isEmpty
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
SizedBox(
height: 50,
),
Icon(
Icons.search,
size: 50,
),
SizedBox(
height: 60,
),
Text(
'Sorry no results found.',
style: TextStyle(fontSize: 20),
),
],
),
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
childAspectRatio: 2 / 3,
mainAxisSpacing: 10,
),
itemCount: prodSearchList.length,
itemBuilder: (context, i) {
if (_searchTextController.text.isNotEmpty) {
return FeedsProduct(
id: _searchList[i].id,
description: _searchList[i].description,
imageUrl: _searchList[i].imageUrl,
isFavorite: _searchList[i].isFavorite,
price: _searchList[i].price,
quantity: _searchList[i].quantity,
);
} else {
return FeedsProduct(
id: prodSearchList[i].id,
description: prodSearchList[i].description,
imageUrl: prodSearchList[i].imageUrl,
isFavorite: prodSearchList[i].isFavorite,
price: prodSearchList[i].price,
quantity: prodSearchList[i].quantity,
);
}
},
),
),
);
}
}
product_controller.dart:
final productControllerProvider = ChangeNotifierProvider<ProductListController>(
(ref) => ProductListController(),
);
class ProductListController extends ChangeNotifier {
// ProductListController([List<Product>? state]) : super();
List<Product> get products => _products;
List<Product> getByCatName(String catName) {
List<Product> catList = _products
.where(
(e) => e.productCategoryName.toLowerCase() == catName.toLowerCase())
.toList();
return catList;
}
List<Product> getByBrandName(String brandName) {
List<Product> brandList = _products
.where((e) => e.brand.toLowerCase() == brandName.toLowerCase())
.toList();
return brandList;
}
List<Product> get popularProducts {
return _products.where((e) => e.isPopular).toList();
}
Product getById(String prodId) {
return _products.firstWhere((e) => e.id == prodId);
}
List<Product> getBySearch(String query) {
List<Product> prodSearchResult = _products
.where(
(e) => e.title.toLowerCase() == query.toLowerCase(),
)
.toList();
notifyListeners();
return prodSearchResult;
}
尝试将 _searchList 创建为 HookState,而不是在您的 class 后期创建。
final _searchList = useState<List<Product>>([]);
onChanged: (val) {
_searchList.value = ref.watch(productControllerProvider.notifier).getBySearch(val);
},
而且你的搜索方法有误,你实际上没有 Apple
产品,你有 Apple MacBookAir ...
所以你的等于 e.title.toLowerCase() == query.toLowerCase()
永远不会是真的,如果你真的想搜索忽略大小写并包含您需要使用 RegExp
的单词
List<Product> getBySearch(String query) {
final RegExp regex = RegExp(query, caseSensitive: false);
List<Product> prodSearchResult = _products
.where((e) => e.title.contains(regex))
.toList();
notifyListeners();
return prodSearchResult;
}
我有一个带有通过 useTextEditingController 提供的控制器的文本字段。控制器文本应该是传递给提供者控制器中的函数的值,以搜索相应的产品并显示它们。但是,没有返回任何搜索结果。我已经通过 print() 语句确认读取并假定传递的值是用户输入到文本字段中的值。对于为什么结果(proList)没有返回到回调以供显示,我束手无策。这是相关的代码片段。
请注意,我通过在查询前将搜索文本转换为小写字母来处理区分大小写问题,以确保这不会影响查询。感谢您的帮助或指点。
search_screen.dart
class SearchScreen extends HookConsumerWidget {
static const routeName = '/searchScreen';
SearchScreen({Key? key}) : super(key: key);
late List<Product> _searchList = [];
@override
Widget build(BuildContext context, WidgetRef ref) {
List<Product> prodSearchList =
ref.watch(productControllerProvider.notifier).products;
final _searchTextController = useTextEditingController();
final FocusNode _node = FocusNode();
final _isSearchFieldEmpty = useState<bool>(true);
bool isSearchFieldEmpty() {
return _searchTextController.text.isEmpty;
}
useEffect(() {
_searchTextController.addListener(() {
_isSearchFieldEmpty.value = isSearchFieldEmpty();
});
}, [_searchTextController]);
return Scaffold(
bottomSheet: TextField(
autofocus: true,
controller: _searchTextController,
focusNode: _node,
decoration: kTextInputDecoration.copyWith(
hintText: 'Item name here ...',
filled: true,
fillColor: Theme.of(context).cardColor,
prefixIcon: const Icon(Icons.search),
suffixIcon: IconButton(
onPressed: _searchTextController.text.isEmpty
? null
: () {
_searchTextController.clear();
},
icon: Icon(Icons.close,
color: _searchTextController.text.isNotEmpty
? Colors.red
: Colors.grey),
),
),
onChanged: (val) {
_searchList =
ref.watch(productControllerProvider.notifier).getBySearch(val);
},
),
body: _searchTextController.text.isNotEmpty && _searchList.isEmpty
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
SizedBox(
height: 50,
),
Icon(
Icons.search,
size: 50,
),
SizedBox(
height: 60,
),
Text(
'Sorry no results found.',
style: TextStyle(fontSize: 20),
),
],
),
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10,
childAspectRatio: 2 / 3,
mainAxisSpacing: 10,
),
itemCount: prodSearchList.length,
itemBuilder: (context, i) {
if (_searchTextController.text.isNotEmpty) {
return FeedsProduct(
id: _searchList[i].id,
description: _searchList[i].description,
imageUrl: _searchList[i].imageUrl,
isFavorite: _searchList[i].isFavorite,
price: _searchList[i].price,
quantity: _searchList[i].quantity,
);
} else {
return FeedsProduct(
id: prodSearchList[i].id,
description: prodSearchList[i].description,
imageUrl: prodSearchList[i].imageUrl,
isFavorite: prodSearchList[i].isFavorite,
price: prodSearchList[i].price,
quantity: prodSearchList[i].quantity,
);
}
},
),
),
);
}
}
product_controller.dart:
final productControllerProvider = ChangeNotifierProvider<ProductListController>(
(ref) => ProductListController(),
);
class ProductListController extends ChangeNotifier {
// ProductListController([List<Product>? state]) : super();
List<Product> get products => _products;
List<Product> getByCatName(String catName) {
List<Product> catList = _products
.where(
(e) => e.productCategoryName.toLowerCase() == catName.toLowerCase())
.toList();
return catList;
}
List<Product> getByBrandName(String brandName) {
List<Product> brandList = _products
.where((e) => e.brand.toLowerCase() == brandName.toLowerCase())
.toList();
return brandList;
}
List<Product> get popularProducts {
return _products.where((e) => e.isPopular).toList();
}
Product getById(String prodId) {
return _products.firstWhere((e) => e.id == prodId);
}
List<Product> getBySearch(String query) {
List<Product> prodSearchResult = _products
.where(
(e) => e.title.toLowerCase() == query.toLowerCase(),
)
.toList();
notifyListeners();
return prodSearchResult;
}
尝试将 _searchList 创建为 HookState,而不是在您的 class 后期创建。
final _searchList = useState<List<Product>>([]);
onChanged: (val) {
_searchList.value = ref.watch(productControllerProvider.notifier).getBySearch(val);
},
而且你的搜索方法有误,你实际上没有 Apple
产品,你有 Apple MacBookAir ...
所以你的等于 e.title.toLowerCase() == query.toLowerCase()
永远不会是真的,如果你真的想搜索忽略大小写并包含您需要使用 RegExp
List<Product> getBySearch(String query) {
final RegExp regex = RegExp(query, caseSensitive: false);
List<Product> prodSearchResult = _products
.where((e) => e.title.contains(regex))
.toList();
notifyListeners();
return prodSearchResult;
}