pull to refresh in case 'No data' widget - flutter

I need help in this please i have a RefreshIndicator that loads a ListView when there is data in the database however I want to make the widget return Text widget 'no data' if the table empty instead of the ListView.
but the when the table is empty it error appear
_TypeError (type 'String' is not a subtype of type 'Iterable')
and that will appear in the refresh method i don't know what should i do i appreciate any help thanks in advance.
this the UI for the page
class _onlineResultTab extends State<onlineResultTab> {
List<ResultsModelClass> resultslist = new List();
List<CoursesModelClass> coursesist = new List();
ResultsModelClass resultsModelClass;
CoursesModelClass courseModelClass;
final GlobalKey<RefreshIndicatorState> refreshKey = GlobalKey<RefreshIndicatorState>();
DataApiProvider dataApiProvider = new DataApiProvider();
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
key: refreshKey,
onRefresh: refreshList,
child: _resultwidget(context),
),
);
}
fetchResultDetails() async {
final allRows = await DbHelper.mydb.getOnlineResultList();
allRows.forEach((row) => {
resultsModelClass = ResultsModelClass(
"",
row["Res_Stud_Index"],
row["Res_Stud_Name"],
row["Res_Sem"].toString(),
"",
"",
row["Res_Batch"],
row["Res_Courses"],
row["Res_Grade"],
row["Res_GPA"].toString(),
row["Res_CGPA"],
row["Res_Status"],
row["faculty_desc_e"],
row["major_desc_e"]),
resultslist.add(resultsModelClass)
});
if (this.mounted) {
setState(() {});
}
}
fetchCourse() async {
final allRows = await DbHelper.mydb.getResultcoursesList();
allRows.forEach((row) => {
courseModelClass = CoursesModelClass(
row["Res_Courses"],
row["Res_Grade"],
),
coursesist.add(courseModelClass)
});
if (this.mounted) {
setState(() {});
}
}
List<String> listHeader = ['Student Results Details'];
Widget _resultwidget(context) {
final _size = MediaQuery.of(context).size;
return resultslist.length == 0
? ListView.builder(
controller: ScrollController(),
itemCount: 1,
itemBuilder: (context, index) {
return Center(
child: Padding(
padding: EdgeInsets.only(top: _size.height * 0.4),
child: Text(
"No Result Details !",
style: TextStyle(fontSize: 20),
),
));
},
physics: AlwaysScrollableScrollPhysics(),
)
: new ListView.builder(
itemCount: listHeader.length,
itemBuilder: (context, index) {
//var _size = MediaQuery.of(context).size;
return SingleChildScrollView(
child: Center(
child: Padding(
padding: EdgeInsets.only(bottom: _size.height * 0.02),
child: Column(
children: [
Card(
elevation: 20,
margin: EdgeInsets.symmetric(
horizontal: _size.width * 0.005,
),
child: Container(
height: 50.0,
decoration: BoxDecoration(
color: Theme.of(context).backgroundColor),
child: Center(
child: Text(
'Semester ' +
resultslist[0].Res_Sem +
' Result ',
style: TextStyle(
color: Colors.white,
fontSize: 17,
fontWeight: FontWeight.bold),
),
),
),
),
],
))),
);
},
);
}
the refresh method
Future<String> refreshList() async {
refreshKey.currentState?.show(atTop: false);
//await Future.delayed(Duration(seconds: 10));
var studentIndex;
final allRows = await DbHelper.mydb.MainInfoCehck();
allRows.forEach((row) => {
row["Stud_Index"],
studentIndex = row["Stud_Index"].toString()
//print( row["Stud_Index"].toString())
});
print(studentIndex);
//void refreshResult(String studentIndex)async{
await dataApiProvider.refresh_result(studentIndex);
// }
if (this.mounted) {
setState(() {
coursesist.clear();
resultslist.clear();
fetchResultDetails();
fetchCourse();
});
}
return null;
}
Future<String> refresh_result(String studentIndex) async {
var url = main_urll + "?studentIndex=" + studentIndex.trim();
final response = await http.get(url);
List<ResultDetailsModel> ResulttDetailsListModel = [];
final resultInfo = jsonDecode(response.body)['result_info'];
DbHelper.mydb.deleteTableData("Result");
print('Result informations : ' + resultInfo.toString());
for (Map i in resultInfo) {
ResulttDetailsListModel.add(ResultDetailsModel.fromJson(i));
DbHelper.mydb.saveResultDetails(ResultDetailsModel.fromJson(i));
}
return "";
}

Please check if
resultslist == null or resultslist.isNotEmpty()
for Handling empty list

Related

Recommended books list display based on a string constant returns exception

I need to show recommended books based on a string constant 'Recommended', but when I call, the method it returns
EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE
The following ImageCodecException was thrown resolving an image codec:
Failed to load network image.
Image URL:
Where image is getting fine from firebase along with all other fields. Below is the getrecommendedbooks method that
I do display fields onto the Page. PLEASE HELP.
THANK YOU.
Here is the code:
getSpecifiedBooks(String title) {
// debugPrint("requested book is $title");
if (title == Constants.recommendedConst) {
debugPrint("recommended requested");
return recommendedBooksList;
} else if (title == Constants.latestByMatabConst) {
return latestBooksList;
} else if (title == Constants.onSaleConst) {
return onSaleList;
} else if (title == Constants.favoritesConst) {
return favoriteBookList;
} else if (title == Constants.allItemsConst) {
return bookList;
} else if (title == Constants.searchConst) {
return bookList;
} else {
return [];
}
}
class BookController extends GetxController {
final recommendedBooksList = [].obs;
void onInit() {
fetchBooks();
super.onInit();
}
void fetchBooks() async {
try {
isLoading(true);
var books = await databaseService.getBooks();
// var favoriteBookIDs = await databaseService.getFavoriteBookIDs();
RxList<dynamic> recommendedBooks =
await databaseService.getRecommendedBooks();
RxList<dynamic> latestBooks = await databaseService.getLatestBooks();
RxList<dynamic> onSaleBooks = await databaseService.getOnSaleBooks();
bookList.assignAll(books);
// await getFavoriteBooks(favoriteBookIDs);
recommendedBooksList.assignAll(recommendedBooks);
latestBooksList.assignAll(onSaleBooks);
// latestBooksList.assignAll(latestBooks); //TODO uncomment this line and comment one above it when books data is updated in firebase with createdAt field in books
onSaleList.assignAll(books);
debugPrint("fetched books");
} finally {
isLoading(false);
}
}
Future<RxList> getRecommendedBooks() async {
RxList books = [].obs;
RxInt itemCount = 1.obs;
Query<Map<String, dynamic>> booksQuery = FirebaseFirestore.instance
.collection("books")
.where("isRecommended", isEqualTo: true);
await booksQuery.get().then(
(value) {
for (var doc in value.docs) {
Book bookItem = Book(
author: doc['author'],
title: doc['title'],
price: doc['price'].toDouble(),
coverImage: doc['coverImage'],
bookID: doc.id,
rating: doc['ratings'].toDouble(),
description: doc['description'],
discountPercentage: doc['discountPercentage'],
isLiked: false,
itemCount: itemCount,
);
books.add(bookItem);
}
},
);
return books;
}
Display Recommended Widget:
#override
Widget build(BuildContext context) {
return OutlinedButton(
child: const Text(' Show Recommended Books',
style: TextStyle(color: Colors.white)),
onPressed: () {
// Navigator.push(
// context,
// MaterialPageRoute(builder: (context) => HomePageScreen()),
// );
// Navigator.pop(context);
Get.off(VerticalGrid(verticalGridTitle: Constants.recommendedConst));
},
);
}
}
Image Widget Render:
#override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.fromLTRB(20.0, 20, 20, 20),
child: Column(children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
widget.verticalGridTitle,
style: TextStyle(
color: secondaryColor,
fontSize: 20,
fontWeight: FontWeight.bold),
),
GestureDetector(
onTap: () {
Get.to(() => BookMagazineTapbar(
titleText: widget.verticalGridTitle,
));
},
child: Row(
children: [
Text(
"seeAll".tr,
style: TextStyle(
color: mainColor,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Icon(Icons.arrow_forward, color: mainColor)
],
),
)
],
),
Padding(
padding: const EdgeInsets.fromLTRB(0, 30, 20, 20),
child: Container(
color: Colors.white,
child: GridView.count(
crossAxisCount: 2,
crossAxisSpacing: 2.0,
mainAxisSpacing: 2.0,
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: const NeverScrollableScrollPhysics(),
children: List.generate(bookList.length, (index) {
return Padding(
padding: const EdgeInsets.only(bottom: 18.0),
child: GestureDetector(
onTap: () {
if (cartBookController.isInTheCart(index)) {
} else {}
Get.to(BookDetailsPage(
type: Constants.bookConst,
index: index,
cartButtonText: 'Add to Cart',
));
},
child: MyNetworkImage(
imageUrl: bookList[index].coverImage,
),
),
);
}),
)),
)
])),
);
}

Pagination in the list does not work when I scroll to the very bottom of the list in flutter

Faced a problem. I started to paginate the list so that 10 elements are displayed, when I reach the bottom of the list using controller.position.extentAfter < 30 I check how far we have gone down and if at the very bottom I change the value of isLoadMoreRunning and show CircularProgressIndicator. I will also add +10 elements to the limit variable for each call to display. I seem to have done everything right, but pagination does not work for me, it shows the first 10 elements, and then nothing passes, new elements are not loaded when I scrolled to the very bottom. What could be the problem?
home
late ScrollController controller;
bool isFirstLoadRunning = false;
bool isLoadMoreRunning = false;
bool hasNextStation = true;
int limit = 10;
void _firstLoadStations() async {
final StationCubit stationCubit = BlocProvider.of<StationCubit>(context);
setState(() {
isFirstLoadRunning = true;
});
try {
stationsList =
await stationCubit.getAllPublicChargingStations(limit: limit);
} catch (error) {
print(error);
}
setState(() {
isFirstLoadRunning = false;
});
}
void _loadMoreStations() async {
final StationCubit stationCubit = BlocProvider.of<StationCubit>(context);
if (hasNextStation == true &&
isFirstLoadRunning == false &&
controller.position.extentAfter < 30) {
setState(() {
isLoadMoreRunning = true;
});
limit += 10;
try {
var fetchedStations =
await stationCubit.getAllPublicChargingStations(limit: limit);
if (fetchedStations.isNotEmpty) {
setState(() {
stationsList.addAll(fetchedStations);
});
} else {
setState(() {
hasNextStation = false;
});
}
} catch (error) {
print(error);
}
setState(() {
isLoadMoreRunning = false;
});
}
// _foundAddressesInStationList = stationsList;
}
#override
void initState() {
_firstLoadStations();
controller = ScrollController()
..addListener(() {
_loadMoreStations();
});
_foundAddresses = _allAddresses;
_foundStation = _allStation;
super.initState();
}
#override
void dispose() {
controller.removeListener(() {
_loadMoreStations();
});
super.dispose();
}
#override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
final double paddingTop = MediaQuery.of(context).padding.top;
final StationCubit stationCubit = BlocProvider.of<StationCubit>(context);
return Container(
width: size.width,
height: size.height,
child: _child(size, paddingTop, stationCubit),
);
}
Widget _child(Size size, double paddingTop, StationCubit stationCubit) =>
BlocBuilder<StationCubit, StationState>(
builder: (context, state) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 8),
child: Column(
children: [
const SizedBox(height: 17),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
_addresses(size, stationCubit),
],
),
),
),
],
),
),
);
Widget _addresses(Size size, StationCubit stationCubit) => ConstrainedBox(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height / 2,
),
child: SizedBox(
width: size.width,
child: ClipRRect(
borderRadius: BorderRadius.circular(24),
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 8.0, sigmaY: 8.0),
child: Container(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
isFirstLoadRunning
? const CircularProgressIndicator(
color: Colors.white)
: const Text(
'Addresses',
style: constants.Styles.smallBookTextStyleWhite,
),
const SizedBox(height: 25),
ListViewSearch(
stationList: stationsList,
controller: controller,
),
const SizedBox(height: 20),
if (isLoadMoreRunning == true)
const Padding(
padding: EdgeInsets.only(top: 10, bottom: 40),
child: Center(
child: CircularProgressIndicator(),
),
),
if (hasNextStation == false)
Container(
padding: const EdgeInsets.only(top: 30, bottom: 40),
color: Colors.amber,
child: const Center(
child:
Text('You have fetched all of the content'),
),
),
],
),
)),
),
),
),
);
}
cubit
Future<List<PublicChargingStationModel>> getAllPublicChargingStations(
{required int limit}) async {
var result =
await StationRepository().getAllPublicChargingStations(limit: limit);
return result;
}
repository
Future<List<PublicChargingStationModel>> getAllPublicChargingStations(
{int? limit}) async {
try {
var apiKeyMap = await ApiKey.getCryptoApiKeyMap();
apiKeyMap!.addAll({'limit': limit.toString()});
final Uri url = Uri.parse(
'${ApiConfig.schema}://${ApiConfig.domain}/${ApiConfig.uriPrefix}/stations',
).replace(queryParameters: apiKeyMap);
final response = await http.get(url);
if (response.statusCode == 200) {
final data = jsonDecode(response.body)['data'] as List;
return data
.map((json) => PublicChargingStationModel.fromJson(json))
.toList();
}
return List<PublicChargingStationModel>.empty();
} catch (_) {
print(_);
return List<PublicChargingStationModel>.empty();
}
}
you need set SingleChildScrollView parameter controller: controller.

I want to filter using CheckboxListTile in flutter but i have not showing any reflection of filtering in listview when i use Alert dialog?

I filter the one litview builder list to another checkbox list and this is working, but when i add this CheckboxListTile in Alert dialog when no filter reflection showing.
I used StatefulBuilder also but is not useful to filtering listview.
[This is first link to show Product list data][1]
This is second link of filter list
I am stuck in how to one data filter to another item filter that availiable in Alert dialog.
This is Api link
const String baseUrl = "https://run.mocky.io/v3/";
const String productDataUrl = baseUrl + "4ecbd2ea-a725-438b-b8fc-da8fc08bc875";
const String productCategoryDataUrl =
baseUrl + "0595387e-732e-47cf-9675-244fed9fc014";
This is product model class that listview model that we want to filter
class ProductDataModel {
int? productId;
String? productName;
int? productPrice;
int? productKG;
String? productCategoryId;
ProductDataModel(
{this.productId,
this.productName,
this.productPrice,
this.productKG,
this.productCategoryId});
ProductDataModel.fromJson(Map<String, dynamic> json) {
productId = json['ProductId'];
productName = json['ProductName'];
productPrice = json['ProductPrice'];
productKG = json['ProductKG'];
productCategoryId = json['ProductCategoryId'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ProductId'] = this.productId;
data['ProductName'] = this.productName;
data['ProductPrice'] = this.productPrice;
data['ProductKG'] = this.productKG;
data['ProductCategoryId'] = this.productCategoryId;
return data;
}
}
This ProductCategory Model class for using filter and this model class
data in CheckboxTile
class ProductCategoryDataModel {
int? productCategoryId;
String? productCategoryName;
bool? isChecked=false;
ProductCategoryDataModel(
{this.productCategoryId, this.productCategoryName, this.isChecked});
ProductCategoryDataModel.fromJson(Map<String, dynamic> json) {
productCategoryId = json['ProductCategoryId'];
productCategoryName = json['ProductCategoryName'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['ProductCategoryId'] = this.productCategoryId;
data['ProductCategoryName'] = this.productCategoryName;
return data;
}
}
This is code of showing listview and filter data using
checkboxlisttile that data in Alert dialog .
import 'dart:convert';
import 'dart:developer';
import 'package:dummy_checkbox_filter_list/commons/api_url.dart';
import 'package:dummy_checkbox_filter_list/model/product_category_data_model.dart';
import 'package:dummy_checkbox_filter_list/model/product_data_model.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<ProductDataModel> productDataList = [];
Set<ProductDataModel> productDataListDisplay = {};
List<ProductCategoryDataModel> productCategoryDataList = [];
List<ProductCategoryDataModel> selectProductCategoryDataList = [];
ScrollController scrollController = ScrollController();
bool isShowLoader = false;
getProductList() async {
try {
setState(() {
isShowLoader = true;
});
final response = await http.get(Uri.parse(productDataUrl));
log("Response URL=> ${response.toString()}");
if (response.statusCode == 200) {
var decode = jsonDecode(response.body);
log("Response Body=> ${decode.toString()}");
for (int i = 0; i < decode.length; i++) {
productDataList.add(ProductDataModel.fromJson(decode[i]));
}
setState(() {
isShowLoader = false;
});
return productDataList;
} else {
setState(() {
isShowLoader = false;
});
throw "Unable to retrieve product data.";
}
} catch (e) {
setState(() {
isShowLoader = false;
});
print('Something went wrong.');
}
}
getProductCategoryList() async {
try {
setState(() {
isShowLoader = true;
});
final response = await http.get(Uri.parse(productCategoryDataUrl));
log("Response URL=> ${response.toString()}");
if (response.statusCode == 200) {
var decode = jsonDecode(response.body);
log("Response Body=>${decode.toString()}");
for (int i = 0; i < decode.length; i++) {
productCategoryDataList
.add(new ProductCategoryDataModel.fromJson(decode[i]));
}
setState(() {
isShowLoader = false;
});
return productCategoryDataList;
} else {
setState(() {
isShowLoader = false;
});
throw "Unable to retrieve product data.";
}
} catch (e) {
setState(() {
isShowLoader = false;
});
print('Something went wrong.');
}
}
#override
void initState() {
getProductList();
getProductCategoryList();
super.initState();
}
#override
Widget build(BuildContext context) {
filterProduct(productDataList);
return Scaffold(
body: SafeArea(
child: isShowLoader == false
? SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
titlePadding: EdgeInsets.zero,
backgroundColor: Color(0xFF242424),
title: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: Icon(
Icons.close,
color: Colors.white,
size: 25,
))
],
),
contentPadding: EdgeInsets.zero,
content: Container(
padding: EdgeInsets.all(5),
width: double.maxFinite,
child: ListView(
padding: EdgeInsets.all(8.0),
children: [
Text(
"dfff "+productCategoryDataList[0].isChecked.toString(),
style: TextStyle(
color: Colors.white,
fontSize: 16),
),
...productCategoryDataList
.map((e) => CheckboxListTile(
controlAffinity:
ListTileControlAffinity
.leading,
title: Text(
"${e.productCategoryName}",
style: TextStyle(
color: Colors.white,
fontSize: 16),
),
value: e.isChecked,
selected:
selectProductCategoryDataList
.contains(e),
onChanged: (val) {
print("val: "+val.toString());
setState(() {
e.isChecked = val;
selectProductCategoryDataList
.contains(e)
? selectProductCategoryDataList
.remove(e)
: selectProductCategoryDataList
.add(e);
print(
"_isChecked: ${e.isChecked}");
});
},
))
],
),
),
);
},
);
});
},
style: ElevatedButton.styleFrom(
primary: Colors.black,
onPrimary: Colors.white,
minimumSize: Size(
MediaQuery.of(context).size.width * 0.30,
MediaQuery.of(context).size.height * 0.05)),
child: Text(
"Filter",
style: TextStyle(fontSize: 15),
),
),
Container(
child: ListView.builder(
itemCount: productDataListDisplay.length,
shrinkWrap: true,
controller: scrollController,
itemBuilder: (context, index) {
return Card(
child: Container(
padding: EdgeInsets.only(top: 15, bottom: 15),
color: (index % 2 == 0)
? Colors.grey.shade100
: Colors.white,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(productDataListDisplay
.elementAt(index)
.productId
.toString()),
Center(
child: Text(
productDataListDisplay
.elementAt(index)
.productName
.toString(),
),
),
Center(
child: Text(
"${productDataListDisplay.elementAt(index).productKG.toString()} KG",
),
),
Center(
child: Text(
"${productDataListDisplay.elementAt(index).productCategoryId.toString()}",
),
),
],
),
),
);
},
),
),
],
),
)
: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue)),
),
),
);
}
void filterProduct(allProducts) {
productDataListDisplay.clear();
if (selectProductCategoryDataList != null &&
selectProductCategoryDataList.isNotEmpty) {
final List<int> idsOfSelectedCategories = selectProductCategoryDataList
.map((category) => category.productCategoryId!)
.toList();
print("idsOfSelectedCategories=> $idsOfSelectedCategories");
Set<ProductDataModel> storesInSelectedCategories =
getStoresFromSelectedCategories(allProducts, idsOfSelectedCategories);
setState(() {
productDataListDisplay.addAll(storesInSelectedCategories);
print(allProducts.length);
print(storesInSelectedCategories.length);
});
} else {
setState(() {
productDataListDisplay.addAll(allProducts);
});
}
}
Set<ProductDataModel> getStoresFromSelectedCategories(
List<ProductDataModel> allProducts, List<int> idsOfSelectedCategories) {
Set<ProductDataModel> allProductsFromCategory = {};
for (var categoryId in idsOfSelectedCategories) {
var productMatched = allProducts
.where((store) => store.productCategoryId!
.split(" ")
.contains(categoryId.toString()))
.toList();
print("Stores Matched runtime=>${productMatched.runtimeType}");
allProductsFromCategory.addAll(productMatched);
}
return allProductsFromCategory;
}
}
Add .then((value) {if (mounted) {setState(() {});}}); to showdialog so that state gets refreshed when alertdialog closes.
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
List<ProductDataModel> productDataList = [];
Set<ProductDataModel> productDataListDisplay = {};
List<ProductCategoryDataModel> productCategoryDataList = [];
List<ProductCategoryDataModel> selectProductCategoryDataList = [];
ScrollController scrollController = ScrollController();
bool isShowLoader = false;
getProductList() async {
try {
setState(() {
isShowLoader = true;
});
final response = await http.get(Uri.parse(productDataUrl));
log("Response URL=> ${response.toString()}");
if (response.statusCode == 200) {
var decode = jsonDecode(response.body);
log("Response Body=> ${decode.toString()}");
for (int i = 0; i < decode.length; i++) {
productDataList.add(ProductDataModel.fromJson(decode[i]));
}
setState(() {
isShowLoader = false;
});
return productDataList;
} else {
setState(() {
isShowLoader = false;
});
throw "Unable to retrieve product data.";
}
} catch (e) {
setState(() {
isShowLoader = false;
});
print('Something went wrong.');
}
}
getProductCategoryList() async {
try {
setState(() {
isShowLoader = true;
});
final response = await http.get(Uri.parse(productCategoryDataUrl));
log("Response URL=> ${response.toString()}");
if (response.statusCode == 200) {
var decode = jsonDecode(response.body);
log("Response Body=>${decode.toString()}");
for (int i = 0; i < decode.length; i++) {
productCategoryDataList
.add(new ProductCategoryDataModel.fromJson(decode[i]));
}
setState(() {
isShowLoader = false;
});
return productCategoryDataList;
} else {
setState(() {
isShowLoader = false;
});
throw "Unable to retrieve product data.";
}
} catch (e) {
setState(() {
isShowLoader = false;
});
print('Something went wrong.');
}
}
#override
void initState() {
getProductList();
getProductCategoryList();
super.initState();
}
#override
Widget build(BuildContext context) {
filterProduct(productDataList);
return Scaffold(
body: SafeArea(
child: isShowLoader == false
? SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
titlePadding: EdgeInsets.zero,
backgroundColor: const Color(0xFF242424),
title: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: const Icon(
Icons.close,
color: Colors.white,
size: 25,
))
],
),
contentPadding: EdgeInsets.zero,
content: Container(
padding: EdgeInsets.all(5),
width: double.maxFinite,
child: ListView(
padding: EdgeInsets.all(8.0),
children: [
Text(
"dfff ${productCategoryDataList[0].isChecked}",
style: const TextStyle(
color: Colors.white,
fontSize: 16),
),
...productCategoryDataList
.map((e) => CheckboxListTile(
controlAffinity:
ListTileControlAffinity
.leading,
title: Text(
"${e.productCategoryName}",
style: const TextStyle(
color: Colors.white,
fontSize: 16),
),
value: e.isChecked,
selected:
selectProductCategoryDataList
.contains(e),
onChanged: (val) {
print("val: $val");
setState(() {
e.isChecked = val;
selectProductCategoryDataList
.contains(e)
? selectProductCategoryDataList
.remove(e)
: selectProductCategoryDataList
.add(e);
print(
"_isChecked: ${e.isChecked}");
});
},
))
],
),
),
);
},
);
}).then((value) {
if (mounted) {
setState(() {});
}
});
},
style: ElevatedButton.styleFrom(
primary: Colors.black,
onPrimary: Colors.white,
minimumSize: Size(
MediaQuery.of(context).size.width * 0.30,
MediaQuery.of(context).size.height * 0.05)),
child: const Text(
"Filter",
style: TextStyle(fontSize: 15),
),
),
Container(
child: ListView.builder(
itemCount: productDataListDisplay.length,
shrinkWrap: true,
controller: scrollController,
itemBuilder: (context, index) {
return Card(
child: Container(
padding: EdgeInsets.only(top: 15, bottom: 15),
color: (index % 2 == 0)
? Colors.grey.shade100
: Colors.white,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(productDataListDisplay
.elementAt(index)
.productId
.toString()),
Center(
child: Text(
productDataListDisplay
.elementAt(index)
.productName
.toString(),
),
),
Center(
child: Text(
"${productDataListDisplay.elementAt(index).productKG.toString()} KG",
),
),
Center(
child: Text(
"${productDataListDisplay.elementAt(index).productCategoryId.toString()}",
),
),
],
),
),
);
},
),
),
],
),
)
: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.blue)),
),
),
);
}
void filterProduct(allProducts) {
productDataListDisplay.clear();
if (selectProductCategoryDataList != null &&
selectProductCategoryDataList.isNotEmpty) {
final List<int> idsOfSelectedCategories = selectProductCategoryDataList
.map((category) => category.productCategoryId!)
.toList();
print("idsOfSelectedCategories=> $idsOfSelectedCategories");
Set<ProductDataModel> storesInSelectedCategories =
getStoresFromSelectedCategories(allProducts, idsOfSelectedCategories);
setState(() {
productDataListDisplay.addAll(storesInSelectedCategories);
print(allProducts.length);
print(storesInSelectedCategories.length);
});
} else {
setState(() {
productDataListDisplay.addAll(allProducts);
});
}
}
Set<ProductDataModel> getStoresFromSelectedCategories(
List<ProductDataModel> allProducts, List<int> idsOfSelectedCategories) {
Set<ProductDataModel> allProductsFromCategory = {};
for (var categoryId in idsOfSelectedCategories) {
var productMatched = allProducts
.where((store) => store.productCategoryId!
.split(" ")
.contains(categoryId.toString()))
.toList();
print("Stores Matched runtime=>${productMatched.runtimeType}");
allProductsFromCategory.addAll(productMatched);
}
return allProductsFromCategory;
}
}

Flutter Tried calling: [] error on list builder

I am showing list-builder i need to show just a static data right now I am just check itemCount right now later'll show data but it's showing error .
Here is my code
class _OrderPageState extends State<OrderPage> {
bool showCards = false;
var data;
#override
void initState() {
this.getOrders();
}
getOrders() async{
final storage = new FlutterSecureStorage();
String userId = await storage.read(key: "_userID");
String url =
'http://retailapi.airtechsolutions.pk/api/orders/customer/${userId}/0';
print(url);
http.Response res = await http.get(
url,
);
var data = json.decode(res.body.toString());
print(data);
if(data['description'].toString() == "Success"){
print(data['Orders']);
print(data['Orders'].length); //its printing 6 here
setState(() {
showCards = true;
});}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Order', style: Theme.of(context).textTheme.headline4),
),
body: showCards ? Container(
child: ListView.builder(
itemCount: data['Orders'].length,
shrinkWrap: true,
padding: EdgeInsets.symmetric(horizontal: 18.0, vertical: 20.0),
itemBuilder: (context, index) {
var order = orderList[index];
return SideInAnimation(index, child:GestureDetector(
onTap: () {
// Get.to(OrderDetailPage(order: order));
},
child: Container(
width: double.infinity,
padding: EdgeInsets.all(12.0),
margin: EdgeInsets.only(bottom: 15.0),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15.0),
border: Border.all(color: Theme.of(context).accentColor),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(order.id,
style: Theme.of(context)
.textTheme
.headline3
.copyWith(color: Theme.of(context).primaryColor)),
SizedBox(height: 12.0),
Text(order.dateOrder, style: Theme.of(context).textTheme.subtitle2),
Divider(),
orderCardItem(context,
title: "order.orderstatus", data: order.orderStatus),
SizedBox(height: 12.0),
orderCardItem(context,
title: "order.items",
data: "${order.totalItem} " + tr("order.itemspurchased")),
SizedBox(height: 12.0),
priceItem(context,
title: "order.price", data: "\$ ${order.totalPrice}"),
],
),
),
));
},
),
) : Container(),
);
}
}
In my function its printing the length by in List builder its showing an error that Tried calling: ` But on the print where API load it's showing the length 6.
First you need to initalize a list or array then simply add your data into that variable and then call this variable to your listview builder
var ordersData = [];
then your getData() method should be like this
getOrders() async {
...
if (data['description'].toString() == "Success") {
ordersData.add(data['Orders']); // Add your data to array or list
print(ordersData.length); //its printing 6 here
}
...
}
Here your Listview like this
ListView.builder(
itemCount: ordersData.length, // Here you need to pass this lenght
...
)

Pagination with flutter gridview fails

I am trying to integrate pagination with gridview.builder,it's working in listview without any problem but in gridview it doesn't work as expected,The problem i am facing is The API data is returns 20 data per page,
Problem:In API it returns 20 data/page,in this API it returns total of 21 data,in 1 st page contains 20 data 2nd page contains only 1 data the pagination is working i can load data but i cannot scroll back to page 1 data it just stuck with page 2 data
I am following this Tutorial,this is working with listview without no problem but in gridview the above problem occurs
InitState and Variable initialization
var page = 1;
ScrollController _sccontroller = new ScrollController();
#override
void initState() {
super.initState();
Future token = SharedPrefrence().getToken();
token.then((data) async {
userToken = data;
this.getSearchResult(page);
_sccontroller.addListener(() {
if (_sccontroller.position.pixels ==
_sccontroller.position.maxScrollExtent) {
getSearchResult(page);
}
});
});
setState(() {
title = name;
});
}
#override
void dispose() {
_sccontroller.dispose();
super.dispose();
}
Gridview
GridView.builder(
controller: _sccontroller,
itemCount: search_result_list.length + 1,
physics: const AlwaysScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(childAspectRatio: 5.2 / 8.0,
crossAxisCount: 2, crossAxisSpacing: 3.0, mainAxisSpacing: 3.0),
itemBuilder: (BuildContext context, int index) {
if (index == search_result_list.length) {
return Center(child: Padding(padding: const EdgeInsets.all(8.0), child: CircularProgressIndicator(),));
} else {
return Container(
child: Padding(
padding: const EdgeInsets.only(top:10),
child: GestureDetector(
onTap: () {
},
child: Container(
// height: 700,
child: Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(2),
),
child: Container(
width: 300,
//height: 500,
child: Stack(
children: [
Column(
mainAxisSize: MainAxisSize.min,
//crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.all(2),
child: Image.network(
Urls.baseImageUrl +
search_result_list[index]
.thumb_path,
fit: BoxFit.fill,
height: 180,
width: 180,
),
),
Padding(
padding: const EdgeInsets.all(5),
child: Align(
child: Text(
search_result_list[index].name,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
alignment: Alignment.centerLeft,
)),
],
),
],
)),
),
),
),
),
);
}
},
)
API Function
Future<void> getSearchResult(int index) async {
print("size" + index.toString());
if (!isLoading) {
setState(() {
isLoading = true;
});
// ProgressDialog dialog = CustomDialogs().showLoadingProgressDialog(context);
List<PrefrenceModel> tList = List();
var response = await http.get(
"${Urls.baseUrl}${Urls.CategorySearch}?latitude=${Constants
.latitude}&longitude=${Constants
.longitude}&radius=100&locale=en&keyword=${slug}&page=${index
.toString()}&type=item",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer ${userToken}",
"Accept": "application/json"
},
);
Map<String, dynamic> value = json.decode(response.body);
if (response.statusCode == 200) {
// dialog.dismissProgressDialog(context);
try {
print("response search " + response.body.toString());
Map<String, dynamic> value = json.decode(response.body);
var status = value['success'];
var message = value['message'];
last_page = value['last_page'];
print(message);
if (status == true) {
search_result_list.clear();
try {
var data = value['data']['data'];
if (data.length > 0) {
for (int i = 0; i < data.length; i++) {
var obj = data[i];
//var petrol_obj = obj['petrolstation'];
search_result_list.add(PrefrenceModel(
obj['id'].toString(),
obj['description'].toString(),
obj['valid_from'].toString(),
obj['valid_to'].toString(),
obj['thumbs']['md'].toString(),
obj['status'].toString(),
"",
"",
obj['name'].toString(),
"",
obj['flyer_slug'].toString(),
obj['type'].toString(),
obj['isClipped'],
obj['url'].toString(),
obj['price'].toString(),
obj['flyer_page_id'].toString(),
obj['id'].toString(),
obj['shop_name'].toString(),
obj['shop_logo'].toString(),
obj['brand_name'].toString(),
obj['brand_logo'].toString(),
));
}
setState(() {
isLoading = false;
search_result_list.addAll(tList);
page++;
});
} else {
final snackBar = SnackBar(content: Text("No Data Available"));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
} catch (e) {
e.toString();
}
} else {
print("Error...");
final snackBar = SnackBar(content: Text(message));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
} catch (e) {
print(e.toString());
}
} else {
var message = value['message'];
// dialog.dismissProgressDialog(context);
final snackBar = SnackBar(content: Text(message));
_scaffoldKey.currentState.showSnackBar(snackBar);
}
}
else
{
setState(() { isLoading = false; });
}
}
Pagination will gives you the data related to the page, for example page one will returns data from 1 to 20, page two from 21 to 40. so you have to add data of page 2 to existed data from page 1. but in your case you are calling search_result_list.clear(); this will erase the old data and put only the new data into the list.