How to filter list item in getx - flutter

I have a to-do app, where I have a list of items with scheduled date and time, title, details, and task done or not. I want to filter the list of todos depending on if its done or not done, How do I implement this in the getx Controller.
Model:
class Todo {
String title;
String details;
String? date;
String? time;
bool done;
bool dateAndTimeEnabled;
int id;
Todo(
{required this.title,
required this.details,
required this.date,
required this.time,
this.dateAndTimeEnabled = true,
required this.id,
this.done = false});
factory Todo.fromJson(Map<String, dynamic> json) => Todo(
id: json['id'],
title: json['title'],
details: json['details'],
done: json['done'],
date: json['date'],
time: json['time'],
dateAndTimeEnabled: json['dateAndTimeEnabled']);
Map<String, dynamic> toJson() => {
'id': id,
'title': title,
'details': details,
'done': done,
'date': date,
'time': time,
'dateAndTimeEnabled': dateAndTimeEnabled
};
}
Getx controller:
class TodoController extends GetxController {
var todos = <Todo>[].obs;
#override
void onInit() {
List? storedTodos = GetStorage().read<List>('todos');
if (storedTodos != null) {
todos.assignAll(storedTodos.map((e) => Todo.fromJson(e)).toList());
}
ever(todos, (_) {
GetStorage().write('todos', todos.toList());
});
super.onInit();
}
}
Update
#override
void initState() {
todoController.getDoneTodos();
super.initState();
}
GestureDetector(
onTap: () {
Get.to(() => const doneTodos());
},
child: Padding(
padding: const EdgeInsets.only(top: 20.0, left: 14.0, right: 12.0),
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('${todoController.doneTodos.length}', style: Theme.of(context).textTheme.headline1,),
Text("Done", style: Theme.of(context).textTheme.headline1)
],),
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 20.0),
height: 138.0,
width: double.infinity,
decoration: BoxDecoration(
color: Theme.of(context).canvasColor,
boxShadow: [
BoxShadow(
color: Theme.of(context).shadowColor,
offset: const Offset(2.5, 2.5),
blurRadius: 5.0,
spreadRadius: 1.0,
),
],
borderRadius:
BorderRadius.circular(14.0))
),
),
),
I tried to wrap the Text widget with Obx but it throws this error: FlutterError (setState() or markNeedsBuild() called during build.

In your controller:
var doneTodos = <Todo>[].obs;
getDoneTodos(){
doneTodo.assignAll(todos.where(element)=>element.done == true).toList());
}

Related

I tried to get data from firestore but display this error "The instance member 'mapRecords' can't be accessed in an initializer. " on Flutter

I tried to get data from firestore but display this error "The instance member 'mapRecords' can't be accessed in an initializer. " on Flutter.
Screenshots of errors
https://drive.google.com/drive/folders/1toBdn9h4-LgBLl5ybG63brgXmk5G0h3F?usp=sharing
my code
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:hexcolor/hexcolor.dart';
import 'package:kathana/utils/config.dart';
import '../screens/wordsBefore18/database/words12model.dart';
class uitry5 extends StatefulWidget {
const uitry5({Key? key}) : super(key: key);
#override
State<uitry5> createState() => _uitry5State();
}
class _uitry5State extends State<uitry5> {
List<String> wordList = [];
Future _fetch = Future(() async {
var records = await FirebaseFirestore.instance.collection('12words').get();
return mapRecords(records);
});
List<Words12> mapRecords(QuerySnapshot<Map<String, dynamic>> records) {
var wordList = records.docs
.map(
(words12) {
print(words12);
return
Words12(
id: words12.id,
wordName: words12['wordName'],
categoryName: words12['categoryName']
);}
.toList();
return wordList;
}
#override
void initState() {
super.initState();
print(wordList);
}
List<String> selectedWord = [];
List<String>? deSelectedWord = [];
#override
Widget build(BuildContext context) {
double height = MediaQuery.of(context).size.height;
double width = MediaQuery.of(context).size.width;
return Scaffold(
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(Config.app_background4), fit: BoxFit.fill),
),
child: SafeArea(
child: Center(
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 14, right: 0),
child: Column(
children: [
SizedBox(
width: width * 0.94,
height: height * 0.30,
child: Column(
children: <Widget>[
const SizedBox(height: 16),
Wrap(
children: wordList.map(
(word) {
bool isSelected = false;
if (selectedWord!.contains(word)) {
isSelected = true;
}
return GestureDetector(
onTap: () {
if (!selectedWord!.contains(word)) {
if (selectedWord!.length < 50) {
selectedWord!.add(word);
deSelectedWord!.removeWhere(
(element) => element == word);
setState(() {});
print(selectedWord);
}
} else {
selectedWord!.removeWhere(
(element) => element == word);
deSelectedWord!.add(word);
setState(() {
// selectedHobby.remove(hobby);
});
print(selectedWord);
print(deSelectedWord);
}
},
child: Container(
margin: const EdgeInsets.symmetric(
horizontal: 5, vertical: 4),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 5, horizontal: 12),
decoration: BoxDecoration(
color: isSelected
? HexColor('#0000FF')
: HexColor('#D9D9D9'),
borderRadius:
BorderRadius.circular(18),
border: Border.all(
color: isSelected
? HexColor('#0000FF')
: HexColor('#D9D9D9'),
width: 2)),
child: Text(
word,
style: TextStyle(
color: isSelected
? Colors.black
: Colors.black,
fontSize: 14,
fontWeight: FontWeight.w600),
),
),
),
);
},
).toList(),
),
],
),
),
],
),
),
],
))),
),
);
}
}
model
import 'dart:convert';
Words12 words12FromJson(String str) => Words12.fromJson(json.decode(str));
String words12ToJson(Words12 data) => json.encode(data.toJson());
class Words12 {
Words12({
required this.id,
required this.wordName,
required this.categoryName,
});
String id;
String wordName;
String categoryName;
factory Words12.fromJson(Map<String, dynamic> json) => Words12(
id: json["id"],
wordName: json["wordName"],
categoryName: json["categoryName"],
);
Map<String, dynamic> toJson() => {
"id": id,
"wordName": wordName,
"categoryName": categoryName,
};
}
How do I resolve this and get data from the database
You can use late before future.
late Future _fetch = ...
Also I will prefer shifting mapRecords before _fetch and FutureBuilder for future.

Unable to load asset(Image) Flutter

This is my API code and I'm passing the image path from here into flutter to determine which image to load. However, all of the other data such as price or title are loading but the image is not loading and throwing an error of unable to load asset.
app.post('/products',(req,res)=>{
//console.log(req.body.LanguageID);
//console.log(req.body.CategoryID);
console.log(req.body);
res.status(200).json({
"StatusCode": 200,
"StatusMessage": "success",
"Data": [
{
"Id": "p8",
"title": "Sufiyan",
"ImageAsset": "assets/images/plant3.png",
"price": 80.0
},
{
"Id": "p8",
"title": "Sufiyan",
"ImageAsset": "assets/images/plant1.png",
"price": 90.0
}
],
"Message": null,
// "localId": '8',
// "idToken": '',
// "error": {
// "message": ""
// },
// "expiresIn": "9"
});
});
app.listen(5000);
That's how I am loading data from the provider into the widget and unable to comprehend why this is not working as I am a newbie to flutter and unable to understand it.
#override
void initState() {
// TODO: implement initState
super.initState();
//gettingData();
final productData = Provider.of<Products>(context, listen: false);
productData.fetchData(context);
// Create TabController for getting the index of current tab
_controller = TabController(length: list.length, vsync: this);
_containerheight = _totalarrayheight(8) * 140;
}
#override
Widget build(BuildContext context) {
final productData = Provider.of<Products>(context);
final products = productData.items;
final featuredProducts = productData.featuredItems;
_controller!.addListener(() {
setState(() {
_selectedIndex = _controller!.index;
if (_controller!.index == 0) {
_containerheight =
140 * _totalarrayheight(products.length.toDouble());
} else {
_containerheight =
140 * _totalarrayheight(featuredProducts.length.toDouble());
}
});
if (kDebugMode) {
print("Selected Index: " + _controller!.index.toString());
}
});
That is my provider code:
class Products with ChangeNotifier {
late List<ProductList> _items = [];
fetchData(context) async {
_items = await getData();
notifyListeners();
}
Widget to create the grid for product
class NewProductGrid extends StatelessWidget {
const NewProductGrid({
Key? key,
required this.products,
}) : super(key: key);
final List<ProductList> products;
#override
Widget build(BuildContext context) {
return StaggeredGridView.countBuilder(
padding: EdgeInsets.only(right: 30, left: 10, top: 10),
physics:
NeverScrollableScrollPhysics(), // to disable GridView's scrolling
shrinkWrap: false,
crossAxisCount: 4,
itemCount: products.length,
itemBuilder: (BuildContext context, int index) => GestureDetector(
onTap: () {
Navigator.of(context).pushNamed(ProductDetail.routeName,
arguments: {'id': products[index].id});
},
child: Container(
//padding: EdgeInsets.only(left:40.0),
child: Column(
children: <Widget>[
Stack(
children: <Widget>[
Padding(
padding: EdgeInsets.only(left: 35.0),
child: Container(
height: 150,
width: 150,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: primary_background_six,
),
),
),
Container(
child: Image.asset(
"${products[index].imageAsset}",
fit: BoxFit.cover,
)),
Container(),
],
),
Padding(
padding: const EdgeInsets.only(left: 20.0),
child: Text(
"\$${products[index].price.toInt()}",
style: TextStyle(fontFamily: 'Morganite Light', fontSize: 50),
),
),
Padding(
padding: const EdgeInsets.only(left: 20.0),
child: Text(
"${products[index].title}",
style: TextStyle(fontFamily: 'PlayFairDisplay', fontSize: 18),
),
),
],
),
),
),
staggeredTileBuilder: (int index) =>
StaggeredTile.count(2, index.isEven ? 3 : 3),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
);
}
}
screen code where the widget is called.
Container(
height: _containerheight,
child: TabBarView(
controller: _controller,
children: <Widget>[
Container(
//height: 140.0 * _totalarrayheight(tagObjs.length.toDouble()),
child: NewProductGrid(
products: products),
)
Product list model code:
import 'package:flutter/material.dart';
class ProductList with ChangeNotifier {
final String id;
final String title;
final String imageAsset;
final num price;
bool isFavorite;
ProductList({
required this.id,
required this.title,
required this.price,
required this.imageAsset,
this.isFavorite = false,
});
factory ProductList.fromMap(Map<String, dynamic> json) {
return ProductList(
id: json['id'],
title: json['title'],
imageAsset: json['imageAsset'],
price: json['price']);
}
factory ProductList.fromJson(Map<String, dynamic> json) {
print('Json:');
print(json);
return ProductList(
id: json['id'] ?? '',
title: json['title'] ?? '',
imageAsset: json['imageAsset'] ?? '',
price: json['price'] ?? 0);
}
void toggleFavoriteStatus() {
isFavorite = !isFavorite;
notifyListeners();
}
}
The image asset in response has an upper case i and the model of product list has image asset with lower case i
Change the model to this
import 'package:flutter/material.dart';
class ProductList with ChangeNotifier {
final String id;
final String title;
final String imageAsset;
final num price;
bool isFavorite;
ProductList({
required this.id,
required this.title,
required this.price,
required this.imageAsset,
this.isFavorite = false,
});
factory ProductList.fromMap(Map<String, dynamic> json) {
return ProductList(
id: json['id'],
title: json['title'],
imageAsset: json['ImageAsset'],
price: json['price']);
}
factory ProductList.fromJson(Map<String, dynamic> json) {
print('Json:');
print(json);
return ProductList(
id: json['id'] ?? '',
title: json['title'] ?? '',
imageAsset: json['ImageAsset'] ?? '',
price: json['price'] ?? 0);
}
void toggleFavoriteStatus() {
isFavorite = !isFavorite;
notifyListeners();
}
}

How to do infinite scrolling in flutter?

I want to scroll infinitely as much my product has. I have total 412 pages. When I scroll to the end I want to show more item of next pages. that means infinite scrolling. how to do this? i have implemented the ScrollController.
this is my Api:
https://www.moharaj.com.bd/api/new/collection/products?page=1
this is my model class:
// To parse this JSON data, do
//
// final newCollectionProductModel = newCollectionProductModelFromJson(jsonString);
import 'dart:convert';
NewCollectionProductModel newCollectionProductModelFromJson(String str) =>
NewCollectionProductModel.fromJson(json.decode(str));
String newCollectionProductModelToJson(NewCollectionProductModel data) =>
json.encode(data.toJson());
class NewCollectionProductModel {
NewCollectionProductModel({
required this.currentPage,
required this.data,
required this.firstPageUrl,
required this.from,
required this.lastPage,
required this.lastPageUrl,
required this.nextPageUrl,
required this.path,
required this.perPage,
required this.prevPageUrl,
required this.to,
required this.total,
});
final int currentPage;
final List<Datum> data;
final String firstPageUrl;
final int from;
final int lastPage;
final String lastPageUrl;
final String nextPageUrl;
final String path;
final int perPage;
final dynamic prevPageUrl;
final int to;
final int total;
factory NewCollectionProductModel.fromJson(Map<String, dynamic> json) =>
NewCollectionProductModel(
currentPage: json["current_page"],
data: List<Datum>.from(json["data"].map((x) => Datum.fromJson(x))),
firstPageUrl: json["first_page_url"],
from: json["from"],
lastPage: json["last_page"],
lastPageUrl: json["last_page_url"],
nextPageUrl: json["next_page_url"],
path: json["path"],
perPage: json["per_page"],
prevPageUrl: json["prev_page_url"],
to: json["to"],
total: json["total"],
);
Map<String, dynamic> toJson() => {
"current_page": currentPage,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
"first_page_url": firstPageUrl,
"from": from,
"last_page": lastPage,
"last_page_url": lastPageUrl,
"next_page_url": nextPageUrl,
"path": path,
"per_page": perPage,
"prev_page_url": prevPageUrl,
"to": to,
"total": total,
};
}
class Datum {
Datum({
required this.id,
required this.name,
required this.price,
required this.salePrice,
required this.slug,
required this.discount,
required this.thumnail,
required this.productImage,
});
final int id;
final String name;
final String price;
final String salePrice;
final String slug;
final int discount;
final String thumnail;
final List<ProductImage> productImage;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
id: json["id"],
name: json["name"],
price: json["price"],
salePrice: json["sale_price"],
slug: json["slug"],
discount: json["discount"],
thumnail: json["thumnail"],
productImage: List<ProductImage>.from(
json["product_image"].map((x) => ProductImage.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"price": price,
"sale_price": salePrice,
"slug": slug,
"discount": discount,
"thumnail": thumnail,
"product_image":
List<dynamic>.from(productImage.map((x) => x.toJson())),
};
}
class ProductImage {
ProductImage({
required this.id,
required this.productId,
required this.productImage,
required this.createdAt,
required this.prefixUrl,
required this.updatedAt,
});
final int id;
final int productId;
final String productImage;
final DateTime createdAt;
final String prefixUrl;
final DateTime updatedAt;
factory ProductImage.fromJson(Map<String, dynamic> json) => ProductImage(
id: json["id"],
productId: json["product_id"],
productImage: json["product_image"],
createdAt: DateTime.parse(json["created_at"]),
prefixUrl: json["prefix_url"],
updatedAt: DateTime.parse(json["updated_at"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"product_id": productId,
"product_image": productImage,
"created_at": createdAt.toIso8601String(),
"prefix_url": prefixUrl,
"updated_at": updatedAt.toIso8601String(),
};
}
this is my Service class Code:
import 'dart:convert';
import 'package:infinite_pagination/NewArrival.dart';
import 'package:infinite_pagination/NewCollectionProductModel.dart';
import 'package:http/http.dart' as http;
/**
* This is a Service Class.
* This Service Class is used for New COllection Product.
*
*/
class NewCollectionProductService {
static var product;
static Future<NewCollectionProductModel>
getNewCollectionProductService() async {
try {
final response = await http.get(Uri.parse(
"https://www.moharaj.com.bd/api/new/collection/products?page=$pageNumber"));
//print(response);
if (response.statusCode == 200 || response.statusCode == 201) {
final decode = jsonDecode(response.body);
product = NewCollectionProductModel.fromJson(decode);
return product;
} else {
return product;
}
} catch (error) {
throw Exception();
}
}
}
this is product Class:
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
var size = 180.0;
var iconSize = 10.0;
Widget Products(String ImgLocation, name, price, discountPrice, discountPercent,
reviews, BuildContext context) {
return Container(
height: 300,
child: Card(
child: Padding(
padding: EdgeInsets.all(5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.network(
'$ImgLocation',
fit: BoxFit.cover,
loadingBuilder: (context, child, loadingProgress) {
return loadingProgress == null
? child
: Center(
child: LinearProgressIndicator(
value: loadingProgress.expectedTotalBytes != null
? loadingProgress.cumulativeBytesLoaded /
loadingProgress.expectedTotalBytes!
: null,
));
// : LinearProgressIndicator();
},
width: MediaQuery.of(context).size.width,
height: size,
),
),
),
Text(
'$name',
textAlign: TextAlign.start,
),
Text(
'৳ $price',
style: TextStyle(
fontSize: 15,
color: Colors.red,
fontWeight: FontWeight.bold),
textAlign: TextAlign.left,
),
Text.rich(
TextSpan(
children: <TextSpan>[
// ignore: unnecessary_new
TextSpan(
text: '৳ $discountPercent',
style: const TextStyle(
color: Colors.grey,
decoration: TextDecoration.lineThrough,
),
),
TextSpan(
text: ' -$discountPrice%',
),
],
),
),
Row(
children: [
Icon(
Icons.star,
color: Color(0xFFFfebf50),
size: iconSize,
),
Icon(
Icons.star,
color: Color(0xFFFfebf50),
size: iconSize,
),
Icon(
Icons.star,
color: Color(0xFFFfebf50),
size: iconSize,
),
Icon(
Icons.star,
color: Color(0xFFFfebf50),
size: iconSize,
),
Icon(
Icons.star,
color: Color(0xFFFfee9c3),
size: iconSize,
),
SizedBox(
width: 5,
),
Text(
'($reviews)',
style: TextStyle(fontSize: iconSize),
)
],
)
],
)),
),
);
}
this is my home page:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:infinite_pagination/NewArrivalController.dart';
import 'package:infinite_pagination/NewCollectionProductModel.dart';
import 'package:infinite_pagination/NewCollectionProductService.dart';
import 'package:infinite_pagination/Products.dart';
//------------------------------------------------------------
// this widget is for Upcoming categories
//------------------------------------------------------------
class NewArrival extends StatefulWidget {
#override
State<NewArrival> createState() => _NewArrivalState();
}
var pageNumber = 1;
class _NewArrivalState extends State<NewArrival> {
NewArrivalController newArrivalController = Get.put(NewArrivalController());
late Future<NewCollectionProductModel> getData;
ScrollController scrollController = ScrollController();
#override
void initState() {
getData = NewCollectionProductService.getNewCollectionProductService();
// TODO: implement initState
super.initState();
scrollController.addListener(() {
print(scrollController.position.pixels);
if (scrollController.position.pixels ==
scrollController.position.maxScrollExtent) {
pageNumber++;
print(pageNumber);
}
});
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
scrollController.dispose();
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Padding(
padding: EdgeInsets.only(left: 10),
child: Text('New Arrival',
style: TextStyle(
fontSize: 17,
fontWeight: FontWeight.bold,
)),
),
Padding(
padding: const EdgeInsets.all(10.0),
child: MaterialButton(
color: Colors.red,
child: Text("View All"),
onPressed: () {}),
)
],
),
Container(
// height: 200,
child: collectionOfData())
],
),
),
),
);
}
collectionOfData() {
return FutureBuilder<NewCollectionProductModel>(
future: getData,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
controller: scrollController,
physics: NeverScrollableScrollPhysics(),
// scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: snapshot.data!.data.length,
// gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 2),
itemBuilder: (context, int index) {
var product = snapshot.data!.data[index];
//slug = product.slug;
String image = product.productImage[0].prefixUrl.toString() +
product.productImage[0].productImage.toString();
return GestureDetector(
onTap: () {},
child: Container(
height: 300,
width: 200,
child: Products(
image,
product.name,
product.price,
product.discount,
product.salePrice,
product.id,
context,
),
),
);
});
} else {
return Center(child: CircularProgressIndicator());
}
});
}
}
you can manage in 2 ways.
without package: manage scrolling point & total page, current page & per page items.
using pagination_view and other packages.
you can also check the below links.
raywenderlich-pagination
mobikul-pageination
stack-overfllow-query
Simple Example without packages:
Declare the below code initially.
ScrollController _scrollController = new ScrollController();
var pageNumber = 1;// update in API CALL
total_page = 0; // update in API CALL
current_page = 0; // update in API CALL
List<ModelClass> arrList = [];
Add below code init method
_scrollController.addListener(() async {
if (_scrollController.position.pixels ==
_scrollController.position.maxScrollExtent) {
if (currentPage != total) { // on bottom scroll API Call until last page
currentPage += 1;
apiCall(page: currentPage);
}
}
});
If No data is found & add Pull to refresh widget.
Widget noDataFound() {
return RefreshIndicator(
onRefresh: apiCall(),
child: Center(
child: Text('No Data Found!'),
),
);
}
in Build Widget
arrList.isNotEmpty ? ListView.separated(
padding: const EdgeInsets.all(16.0),
separatorBuilder: (c, index) {
return SizedBox(
height: 20.0,
);
},
physics: AlwaysScrollableScrollPhysics(),
controller: _scrollController,
itemCount: arrList.size + 1,
itemBuilder: (_, index) {
if (index == arrList.length) { // Always one widget 'Loading...' added end of list it will Hide/Show based on condtion.
return Visibility(
visible:
current_page != totalPage ? false:true,
child: Center(
child: Text('Loading...',),
);
} else {
return ... listViewItemWidget;
}
}) : noDataFound()
API Call Function
apiCall(int page = 0){
// update all pagenation variables After API get & map data sucessfully
currentPage , Total page , list value
// Add one condition to store data
if (page == 0) { // If Pull to refresh.
arrList.clear();
arrList = [mapData list from API]; // New data load.
} else {
arrList.add([mapData list from API]); // Append new data in old list
}
}
You can look at the infinite_scroll_pagination package
You can use custom ScrollController to listen when to load more items:
import 'package:flutter/widgets.dart';
class InfiniteListenerController extends ScrollController {
final VoidCallback? onLoadMore;
InfiniteListenerController({this.onLoadMore}) {
if(onLoadMore != null) addListener(_endListener);
}
void _endListener() {
if (position.pixels == position.maxScrollExtent) {
onLoadMore?.call();
}
}
#override
void dispose() {
if(onLoadMore != null) removeListener(_endListener);
super.dispose();
}
}

I have a problem while doing API integration in Flutter

While trying to fetch data using API I didn't get the details . Instead of details I only get null.
How should I solve this?
Hera is my Code .
my screen page code
class ModuleListScreen extends StatefulWidget {
const ModuleListScreen({Key? key}) : super(key: key);
#override
_ModuleListScreenState createState() => _ModuleListScreenState();
}
class _ModuleListScreenState extends State<ModuleListScreen> with HttpMixin {
DatabaseHelper _dbHelper = DatabaseHelper();
List<Item> modules = [];
List<UserTable> userdetails = [];
String userId = '';
String accountId = '';
#override
void initState() {
super.initState();
_dbHelper.getAllUserData().then((value)async{
userdetails = value;
var response = await getmoduleList(value[0].userId.toString(),value[0].accountId.toString());
response.forEach((element) {
setState(() {
modules.add(element);
});
print('Test Printing ${element.pkgSequence}');
print('Test Printing ${modules[0].id}');
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.blue.shade300,
appBar: AppBar(
backgroundColor: Colors.pink,
actions: [
Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 3),
color: Colors.blue,
borderRadius: BorderRadius.circular(50)),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Image.asset('assets/images/icons/Back.png'),
)),
)
],
title: Center(child: Text('Subject Name')),
leading: Padding(
padding: const EdgeInsets.all(5.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 3),
color: Colors.blue,
borderRadius: BorderRadius.circular(50)),
child: Padding(
padding: const EdgeInsets.all(5.0),
child: Image.asset('assets/images/icons/ride.png'),
)),
),
),
body: Container(
child:
ListView.builder(
itemCount: modules.length,
itemBuilder: (context, index) {
return Container(
height: MediaQuery.of(context).size.height / 3,
margin: EdgeInsets.all(3),
child: Column(
children: [
Container(
padding: EdgeInsets.fromLTRB(
MediaQuery.of(context).size.height * .15,
5,
MediaQuery.of(context).size.height * .15,
5),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(50),
color: Colors.grey),
child: Text(modules[index].title.toString()),
),
Expanded(
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 0),
child: Container(
height: MediaQuery.of(context).size.height / 3,
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(10),
color: Colors.white,
),
child: ListView.builder(
itemCount: 2,
itemBuilder: (context, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Text(
'{article.chapter}',
style: TextStyle(
color: Colors.grey,
fontSize: 18,
fontWeight: FontWeight.w700),
),
Image(
height: 15,
image: AssetImage(
'assets/images/icons/Download.png'),
)
],
),
);
}),
),
),
)
],
));
})
),
);
}
}
My model page
class ModuleList {
ModuleList({
this.items,
this.subject,
this.grade,
});
List<Item>? items;
String? subject;
String? grade;
factory ModuleList.fromMap(Map<String, dynamic> map) => ModuleList(
items: map["items"] != null ? List<Item>.from(map["items"].map((x) => Item.fromMap(x))):[],
// items: List<Item>.from(json["items"].map((x) => Item.fromJson(x))),
subject: map["subject"],
grade: map["grade"],
);
Map<String, dynamic> toMap() => {
"items": items,
"subject": subject,
"grade": grade,
};
}
class Item {
Item({
this.sequenceno,
this.id,
this.chapter,
this.title,
this.packageDescription,
this.ageLevel,
this.pkgSequence,
this.packagescors,
});
int? sequenceno;
String? id;
String? chapter;
String? title;
String? packageDescription;
List<int>? ageLevel;
String? pkgSequence;
List<Packagescors>? packagescors;
Item.fromMap(Map<String, dynamic> map) {
Item(
sequenceno: map["sequenceno"],
id: map["_id"],
chapter: map["chapter"],
title: map["title"],
packageDescription: map["package_description"],
ageLevel: List<int>.from(map["age_level"].map((x) => x)),
pkgSequence: map["pkg_sequence"],
// packagescors: json["packagescors"] != null ? null : Packagescors.fromJson(json["packagescors"]),
packagescors: map["packagescors"] != null
? List<Packagescors>.from(
map["device_details"].map((x) => Packagescors.fromMap(x)))
: [],
);
}
Map<String, dynamic> toMap() => {
"sequenceno": sequenceno,
"_id": id,
"chapter": chapter,
"title": title,
"package_description": packageDescription,
"age_level": List<dynamic>.from(ageLevel!.map((x) => x)),
"pkg_sequence": pkgSequence,
"packagescors": packagescors,
};
}
class Packagescors {
Packagescors({
this.score,
this.date,
});
List<int>? score;
List<String>? date;
factory Packagescors.fromMap(Map<String, dynamic> map) => Packagescors(
score: List<int>.from(map["score"].map((x) => x)),
date: List<String>.from(map["date"].map((x) => x)),
);
Map<String, dynamic> toMap() => {
"score": List<dynamic>.from(score!.map((x) => x)),
"date": List<dynamic>.from(date!.map((x) => x)),
};
}
My http_mixin code for the above model
Future<List<Item>> getmoduleList(
String userId, String accountId) async {
final queryParameters ={
'subject':'Maths',
'grade':'6'
};
final response = await http
.get(Uri.https(_baseUrl, "MY URI",queryParameters), headers: {
'Content-Type': 'application/json',
'user-id': userId,
'account-id': accountId,
});
List <Item> jsonresponse = json.decode(response.body)['data']['items'].map<Item>((e)=>Item.fromMap(e)).toList();
print((response.body));
return jsonresponse;
}
1.This is My code. Here I want to fetch data from API. Now the result I got when I fetch is null.
I created the model using quick type also done some changes in the model.

How do i get the likes fetched to the ui here..the like count is updated in the firebase but does not update in the ui. The code is shown below

The code below works and the like count is updated in the database..but it does not show up on the ui. How can i get the like count in the specific place as shown in the code? In this code it does update to the database ..but it does not show the updated number in the ui. I also used setState in the function to update it to the ui but it still does not show the number which is there in the ui.
class Brew {
final String id;
final String name;
final String sugars;
final int strength;
final int likeCount;
Brew({this.id, this.name, this.sugars, this.strength,
this.likeCount});
}
class BrewData {
final String id;
final String name;
final String sugars;
final int strength;
final int likeCount;
BrewData({this.id, this.name, this.sugars, this.strength,
this.likeCount});
factory BrewData.fromDoc(DocumentSnapshot doc) {
return BrewData(
id: doc.documentID,
name: doc['name'],
sugars: doc['sugars'],
strength: doc['strength'],
likeCount: doc['likeCount'],
);
}
}
class BrewTile extends StatefulWidget {
final Brew brew;
BrewTile({ this.brew});
#override
_BrewTileState createState() => _BrewTileState();
}
class _BrewTileState extends State<BrewTile> {
int _likeCount = 0;
bool _isLiked = false;
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Card(
margin: EdgeInsets.fromLTRB(20.0, 6.0, 20.0, 0.0),
child: ListTile(
leading: CircleAvatar(
radius: 25.0,
backgroundColor: Colors.brown[brew.strength],
backgroundImage:
AssetImage('assets/coffee_icon.png'),
),
title: Text(brew.name),
subtitle: Text('Takes ${brew.sugars} sugar(s)'),
),
),
),
Padding(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
children: <Widget>[
IconButton(
icon: _isLiked
? Icon(
Icons.favorite,
color: Colors.blue,
)
: Icon(Icons.favorite_border),
iconSize: 30.0,
onPressed: () {
if (_isLiked) {
_likeCount++;
_isLiked = false;
print(_likeCount);
DatabaseService()
.updateLikes(id: widget.brew.id, value:
1);
} else {
print(true);
_likeCount--;
_isLiked = true;
DatabaseService()
.updateLikes(id: widget.brew.id, value:
-1);
print(_likeCount);
}
});
},
),
Padding(
padding: EdgeInsets.symmetric(horizontal:
12.0),
child: Text(
'${_likeCount.toString()} likes',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
),
],
)
],
),
)
],
);
}
}
List<Brew> _brewListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.documents.map((doc) {
//print(doc.data);
return Brew(
id: doc.documentID ?? '',
name: doc.data['name'] ?? '',
strength: doc.data['strength'] ?? 0,
sugars: doc.data['sugars'] ?? '0',
likeCount: doc.data['likeCount'] ?? 0,);
}).toList();
}
Future<void> updateLikesCount({String id int value}) async {
return await brewCollection
.document(id)
.updateData({'likeCount': FieldValue.increment(value)});
}
Future<void> updateBrewData(String sugars, String name, int strength, int likeCount) async {
return await brewCollection.document(uid).setData({
'sugars': sugars,
'name': name,
'strength': strength,
'likeCount': likeCount,
});
}
Okay this is a really easy fix in brew_tile.dart make this change
bool _isLiked = false;
int _likeCount;
#override
void initState() {
_likeCount = widget.brew.likeCount;
super.initState();
}
#override
void didUpdateWidget(BrewTile oldWidget) {
if (_likeCount != widget.brew.likeCount) {
_likeCount = widget.brew.likeCount;
print('initState: ${widget.brew.bio} ${widget.brew.likeCount}');
}
super.didUpdateWidget(oldWidget);
}
Padding(
padding: EdgeInsets.symmetric(horizontal: 12.0),
child: Text(
'$_likeCount likes',
style: TextStyle(
fontSize: 16.0,
fontWeight: FontWeight.bold,
),
),
),