How to use index without an item builder in flutter - flutter

I am trying to display a list of cards from firestore on a page. This list is called from another page. If i manually set an integer value, the product displays the cards from that value, but if i do not set an int value, i get an error. How do i get the index of the card without using an itembuilder. Here is the code.
child: Center(
child: InkWell(
onTap: () async {
await productProvider
.loadProductsByCategory(
categoryName: categoryProvider
.categories[0].category);
changeScreen(
context,
CategoryScreen(
categoryModel:
categoryProvider.categories[0],
));
},
child: Text(widget.product.category),
)),
This is where i am having a problem. Just using [0] or any integer works. But i want to call the index, so that once i click on the category, it loads the particular one and all it's products. I have attached the full code.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class NewProductScreen extends StatefulWidget {
final ProductModel product;
const NewProductScreen({Key key, this.product}) : super(key: key);
#override
_NewProductScreenState createState() => _NewProductScreenState();
}
class _NewProductScreenState extends State<NewProductScreen> {
#override
Widget build(BuildContext context) {
final productProvider = Provider.of<ProductProvider>(context);
final categoryProvider = Provider.of<CategoryProvider>(context);
return Scaffold(
body: CustomScrollView(slivers: <Widget>[
SliverToBoxAdapter(
child: Column(
children: <Widget>[
Container(
margin:
EdgeInsets.only(top: 5, bottom: 5, right: 2),
width: MediaQuery
.of(context)
.size
.width / 3,
height: MediaQuery
.of(context)
.size
.height / 30,
child: Center(
child: InkWell(
onTap: () async {
await productProvider.loadProductsByCategory(
categoryName: categoryProvider
.categories[0].category);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CategoryScreen(
categoryModel: categoryProvider
.categories[0],
)));
},
child: Text(widget.product.category),
)),
),
],
),
)
]));
}
}
class CategoryScreen extends StatefulWidget {
final CategoryModel categoryModel;
const CategoryScreen({Key key, this.categoryModel}) : super(key: key);
#override
_CategoryScreenState createState() => _CategoryScreenState();
}
class _CategoryScreenState extends State<CategoryScreen> {
#override
Widget build(BuildContext context) {
final productProvider = Provider.of<ProductProvider>(context);
return Scaffold(
appBar: AppBar(
title: Text("Category Filter"),
),
body: SafeArea(
child: ListView(
children: <Widget>[
Container(
height: MediaQuery
.of(context)
.size
.height / 10,
decoration: BoxDecoration(
color: Colors.orange.withOpacity(0.5),
image: DecorationImage(
image: NetworkImage(widget.categoryModel.icon))),
child: Center(
child: Text(
widget.categoryModel.category,
style: TextStyle(
fontWeight: FontWeight.w700,
fontSize: 50,
),
),
),
),
Column(
children: productProvider.productsByCategory
.map((e) =>
GestureDetector(
onTap: () {
Navigator
.push(context, MaterialPageRoute(builder: (context)
=>
NewProductScreen(
product: e,
)
);
},
child: CategoryProductCard(
product: e,
),
))
.toList(),
)
],
)),
);
}
}
//Category ProductCard
class CategoryProductCard extends StatefulWidget {
final ProductModel product;
const CategoryProductCard({Key key, this.product}) : super(key: key);
#override
_CategoryProductCardState createState() => _CategoryProductCardState();
}
class _CategoryProductCardState extends State<CategoryProductCard> {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 4, right: 4, top: 4, bottom: 10),
child: Container(
height: 110,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(
color: Colors.grey[300],
offset: Offset(-2, -1),
blurRadius: 5),
]),
// height: 160,
child: Row(
children: <Widget>[
Container(
width: 140,
height: 120,
child: ClipRRect(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
topLeft: Radius.circular(20),
),
child: Image.network(
widget.product.images[0],
fit: BoxFit.fill,
),
),
),
Expanded(
child: Column(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(widget.product.title)),
Padding(
padding: EdgeInsets.all(8),
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey[300],
offset: Offset(1, 1),
blurRadius: 4),
]),
),
)
],
),
SizedBox(
height: 25,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Text(
"\N${widget.product.price}",
),
),
],
),
],
),
)
],
),
),
);
}
}
//Category Model
class CategoryModel {
static const ID = "id";
static const CATEGORY = "category";
static const ICON = "icon";
int _id;
String _category;
String _icon;
bool isSelected;
int get id => _id;
String get category => _category;
String get icon => _icon;
CategoryModel.fromSnapshot(DocumentSnapshot snapshot) {
_id = snapshot.data[ID];
_category = snapshot.data[CATEGORY];
_icon = snapshot.data[ICON];
}
}
// Category Provider
class CategoryProvider with ChangeNotifier {
CategoryServices _categoryServices = CategoryServices();
List<CategoryModel> categories = [];
CategoryModel categoryModel;
CategoryProvider.initialize() {
loadCategories();
}
loadCategories() async {
categories = await _categoryServices.getCategories();
notifyListeners();
}
loadSingleCategory({String singleCat}) async {
categoryModel =
await _categoryServices.getCategoryByName(category: singleCat);
notifyListeners();
}
}
// Category Service
class CategoryServices {
String collection = "categories";
Firestore _firestore = Firestore.instance;
Future<List<CategoryModel>> getCategories() async =>
_firestore.collection(collection).getDocuments().then((result) {
List<CategoryModel> categories = [];
for (DocumentSnapshot category in result.documents) {
categories.add(CategoryModel.fromSnapshot(category));
}
return categories;
});
Future<CategoryModel> getCategoryByName({String category}) =>
_firestore
.collection(collection)
.document(category.toString())
.get()
.then((doc) {
return CategoryModel.fromSnapshot(doc);
});
}
// Product Model
class ProductModel {
static const ID = "id";
static const TITLE = "Product Title";
static const Images = "Product Images";
static const PRICE = "Product Price";
static const CATEGORY = "Product Category";
// static const QUANTITY = "Product Quantity";
static const BRAND = "Product Brand";
String _id;
String _title;
List _images;
String _category;
String _brand;
// int _quantity;
double _price;
String get id => _id;
String get title => _title;
List get images => _images;
String get brand => _brand;
String get category => _category;
// int get quantity => _quantity;
double get price => _price.floorToDouble();
ProductModel.fromSnapshot(DocumentSnapshot snapshot) {
_id = snapshot.data[ID];
_brand = snapshot.data[BRAND];
_price = snapshot.data[PRICE];
_category = snapshot.data[CATEGORY];
_title = snapshot.data[TITLE];
_images = snapshot.data[Images];
}
}
class ProductProvider with ChangeNotifier {
ProductServices _productServices = ProductServices();
List<ProductModel> products = [];
List<ProductModel> productsByVendor = [];
List<ProductModel> productsByCategory = [];
ProductProvider.initialize() {
loadProducts();
}
loadProducts() async {
products = await _productServices.getProducts();
notifyListeners();
}
Future loadProductsByCategory({String categoryName}) async {
productsByCategory =
await _productServices.getProductsByCategory(category: categoryName);
notifyListeners();
}
}
class ProductServices {
String collection = "appProducts";
Firestore _firestore = Firestore.instance;
Future<List<ProductModel>> getProducts() async =>
_firestore.collection(collection).getDocuments().then((result) {
List<ProductModel> products = [];
for (DocumentSnapshot product in result.documents) {
products.add(ProductModel.fromSnapshot(product));
}
return products;
});
Future<List<ProductModel>> getProductsByCategory({String category}) async =>
_firestore
.collection(collection)
.where("Product Category", isEqualTo: category)
.getDocuments()
.then((result) {
List<ProductModel> products = [];
for (DocumentSnapshot product in result.documents) {
products.add(ProductModel.fromSnapshot(product));
}
return products;
});
}

You can try below way
final List uniqueList = Set.from(myList).toList();
uniqueList.map((val) {
String idx = uniqueList.indexOf(val);
return something;
}
For Example :
#override
Widget build(BuildContext context) {
var uniqueList = Set.from(['A','B','C','D','E']).toList();
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
children: uniqueList
.map((e) =>
GestureDetector(
onTap: () {
print("--index--${uniqueList.indexOf(e)}");
// Navigator
// .push(context, MaterialPageRoute(builder: (context)
// =>
// NewProductScreen(
// product: e,
// )
// );
},
child: Text('value :$e - index:${uniqueList.indexOf(e)}'),
))
.toList(),
)
),
);
}
Here, You should replace ['A','B','C','D','E'] list to you productProvider.productsByCategory
Output

Related

Search from a list of Firebase Users with TextField and StreamProvider in Flutter

I'm building a chat app with Firebase in flutter and I want to be able to search from a list of users,. I also want that when no text is typed, no user should be shown
I tried a lot of things but I never got it right. This is what I did :
search_page.dart:
class SearchPage extends StatefulWidget {
const SearchPage({Key? key}) : super(key: key);
#override
State<SearchPage> createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> {
TextEditingController searchController = TextEditingController();
#override
void initState() {
super.initState();
searchController.addListener(_onSearchChanged);
}
_onSearchChanged() {
print(searchController.text);
}
#override
void dispose() {
searchController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return StreamProvider<List<AppUserData>>.value(
initialData: [],
value: DatabaseService().users,
child: Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: dDarkGrey,
body:
Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
const SizedBox(
height: 3,
),
Stack(
alignment: Alignment.center,
children: [
Container(
height: 90,
decoration: BoxDecoration(color: dDarkGrey, boxShadow: [
BoxShadow(
color: dBlack.withOpacity(0.16),
spreadRadius: 3,
blurRadius: 3,
offset: const Offset(0, 4))
]),
),
Column(
children: [
const SizedBox(
height: 20,
),
Row(
children: [
IconButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const HomePage()));
},
icon: const Icon(SocketIconv2.ic_back),
color: dLightGrey,
),
SizedBox(
width: MediaQuery.of(context).size.width - 60,
child: TextField(
enabled: true,
controller: searchController,
style: const TextStyle(color: dLightGrey),
decoration: const InputDecoration(
contentPadding:
EdgeInsets.fromLTRB(0, 0, 0, 0),
filled: true,
fillColor: dDarkGrey,
prefixIcon: Icon(
SocketIconv2.ic_search,
color: dLightGrey,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(15))),
hintStyle: TextStyle(
color: dLightGrey,
fontFamily: 'SegoeUI',
fontSize: 18,
fontWeight: FontWeight.w300),
hintText: 'Search',
))),
],
),
],
),
],
),
// search bar
SizedBox(
height: MediaQuery.of(context).size.height - 95,
width: MediaQuery.of(context).size.width,
child: SearchList(
controller: searchController,
),
)
])),
);
}
}
search_list.dart:
class SearchList extends StatelessWidget {
SearchList({Key? key, required this.controller}) : super(key: key);
final TextEditingController controller;
#override
Widget build(BuildContext context) {
final users = Provider.of<List<AppUserData>>(context);
return Scaffold(
backgroundColor: Colors.transparent,
body: ListView.separated(
itemBuilder: (context, index) {
if (controller.text.isEmpty) {
return Container();
}
if (controller.text.isNotEmpty) {
return searchAccount(context, name, username, users[index]);
}
if (users[index].name.startsWith(controller.text.toLowerCase())) {
return searchAccount(context, name, username, users[index]);
} else {
return Container();
}
},
itemCount: users.length,
separatorBuilder: (context, index) => const SizedBox(height: 20),
));
}
}
search_account.dart:
Widget searchAccount(
BuildContext context, String name, String username, AppUserData users) {
return Row(
children: [
const SizedBox(
width: 20,
),
Row(
children: [
ClipOval(
child: Image.asset(
imagePp,
scale: 9,
),
),
const SizedBox(
width: 30,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(users.name,
style: SegoeUiPreset(dLightGrey).customTileName()),
Text(users.username,
style: SegoeUiPreset(dLightGrey).customTileSubtitle())
],
)
],
),
],
);
}
user.dart:
class AppUser {
final String? uid;
AppUser({this.uid});
}
class AppUserData {
final String? uid;
final String name;
final String username;
AppUserData({this.uid, required this.name, required this.username});
}
database.dart:
class DatabaseService {
final String? uid;
DatabaseService({this.uid});
final CollectionReference chatRoomCollection =
FirebaseFirestore.instance.collection("chatrooms");
final CollectionReference userCollection =
FirebaseFirestore.instance.collection("users");
Future<void> saveUser(String name, String username) async {
return await userCollection
.doc(uid)
.set({'name': name, 'username': username});
}
AppUserData _userFromSnapshot(DocumentSnapshot snapshot) {
return AppUserData(
name: snapshot['name'],
uid: snapshot.id,
username: snapshot['username']);
}
Stream<AppUserData> get user {
return userCollection.doc(uid).snapshots().map(_userFromSnapshot);
}
List<AppUserData> _userListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map((doc) {
return _userFromSnapshot(doc);
}).toList();
}
Stream<List<AppUserData>> get users {
return userCollection.snapshots().map(_userListFromSnapshot);
}
}
Got any hints ? I'm a begginner :/
Thank you in advance :)

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.

Everything matches but I still get "Bad state: field does not exist within the DocumentSnapshotPlatform"

So i'm pretty lost trying to get my app to fetch not only the desired text from firestore but also the image i placed there. I know the error "Bad state: field does not exist within the DocumentSnapshotPlatform" implies that either I'm missing field or there's something wrong with at least one of those fields. There's only four things I'm trying to fetch from firestore "imgUrl, title, desc, organizer" i have checked for spelling and order and i can't figure it out. I have also checked firestore to see if the order and spelling was correct and i dont see what's the issue. Please help, Thank you so much in advanced.
////////////////////////////// News Class Starts\\\\\\\\\\\\\\
import 'package:myfuji/screens/CrudMethods.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'CrudMethods.dart';
import 'add_blog.dart';
class News extends StatefulWidget {
#override
_NewsState createState() => _NewsState();
}
class _NewsState extends State<News> {
CrudMethods crudMethods = CrudMethods();
late QuerySnapshot blogSnapshot;
#override
void initState() {
crudMethods.getData().then((result) {
blogSnapshot = result;
setState(() {});
});
super.initState();
}
Widget blogsList() {
return ListView.builder(
padding: const EdgeInsets.only(top: 24),
itemCount: blogSnapshot.docs.length,
itemBuilder: (context, index) {
return BlogTile(
organizer: blogSnapshot.docs[index].get('Organizer'),
desc: blogSnapshot.docs[index].get('desc'),
imgUrl: blogSnapshot.docs[index].get('imgUrl'),
title: blogSnapshot.docs[index].get('title'),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Events"),
),
body: Container(
child: blogSnapshot != null
? blogsList()
: const Center(
child: CircularProgressIndicator(),
)),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (context) => AddBlog()));
},
),
);
}
}
class BlogTile extends StatelessWidget {
final String imgUrl, title, desc, organizer;
const BlogTile(
{required this.organizer,
required this.desc,
required this.imgUrl,
required this.title});
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(bottom: 24, right: 16, left: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(8)),
child: Image.network(
imgUrl,
width: MediaQuery.of(context).size.width,
fit: BoxFit.cover,
height: 200,
),
),
),
const SizedBox(height: 16),
Text(
title,
style: const TextStyle(fontSize: 17),
),
const SizedBox(height: 2),
Text(
'$desc - By $organizer',
style: const TextStyle(fontSize: 14),
)
],
),
);
}
}
///////////////////////////////////////////// class AddBlog begins here \\\\\\\\\\\
import 'dart:io';
import 'package:myfuji/screens/CrudMethods.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:random_string/random_string.dart';
class AddBlog extends StatefulWidget {
#override
_AddBlogState createState() => _AddBlogState();
}
class _AddBlogState extends State<AddBlog> {
//
late File selectedImage;
final picker = ImagePicker();
bool isLoading = false;
CrudMethods crudMethods = new CrudMethods();
Future getImage() async {
final pickedFile = await picker.getImage(source: ImageSource.gallery);
setState(() {
if (pickedFile != null) {
selectedImage = File(pickedFile.path);
} else {
print('No image selected.');
}
});
}
Future<void> uploadBlog() async {
if (selectedImage != null) {
// upload the image
setState(() {
isLoading = true;
});
Reference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("events/")
.child("${randomAlphaNumeric(9)}.jpg");
final UploadTask task = firebaseStorageRef.putFile(selectedImage);
var imageUrl;
await task.whenComplete(() async {
try {
imageUrl = await firebaseStorageRef.getDownloadURL();
} catch (onError) {
print("Error");
}
print(imageUrl);
});
// print(downloadUrl);
Map<String, dynamic> blogData = {
"imgUrl": imageUrl,
"Organizer": authorTextEditingController.text,
"title": titleTextEditingController.text,
"desc": descTextEditingController.text
};
crudMethods.addData(blogData).then((value) {
setState(() {
isLoading = false;
});
Navigator.pop(context);
});
// upload the blog info
}
}
//
TextEditingController titleTextEditingController =
new TextEditingController();
TextEditingController descTextEditingController = new TextEditingController();
TextEditingController authorTextEditingController =
new TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Create Blog"),
actions: [
GestureDetector(
onTap: () {
uploadBlog();
},
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Icon(Icons.file_upload)),
)
],
),
body: isLoading
? Container(
child: Center(
child: CircularProgressIndicator(),
))
: SingleChildScrollView(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
GestureDetector(
onTap: () {
getImage();
},
child: selectedImage != null
? Container(
height: 150,
margin: EdgeInsets.symmetric(vertical: 24),
width: MediaQuery.of(context).size.width,
child: ClipRRect(
borderRadius:
BorderRadius.all(Radius.circular(8)),
child: Image.file(
selectedImage,
fit: BoxFit.cover,
),
),
)
: Container(
height: 150,
decoration: BoxDecoration(
color: Colors.grey,
borderRadius:
BorderRadius.all(Radius.circular(8))),
margin: EdgeInsets.symmetric(vertical: 24),
width: MediaQuery.of(context).size.width,
child: Icon(
Icons.camera_alt,
color: Colors.white,
),
),
),
TextField(
controller: titleTextEditingController,
decoration: InputDecoration(hintText: "enter title"),
),
TextField(
controller: descTextEditingController,
decoration: InputDecoration(hintText: "enter desc"),
),
TextField(
controller: authorTextEditingController,
decoration:
InputDecoration(hintText: "enter author name"),
),
],
)),
),
);
}
}
///////////////////////////////////////////// class CrudMethods begins here \\\\\\\\\\\
import 'package:cloud_firestore/cloud_firestore.dart';
class CrudMethods {
Future<void> addData(blogData) async {
print(blogData);
FirebaseFirestore.instance
.collection("events/")
.add(blogData)
.then((value) => print(value))
.catchError((e) {
print(e);
});
}
getData() async {
return await FirebaseFirestore.instance.collection("events/").get();
}
}
/////////////////////////////////////////////firestore\\\\\\\\\\\\\
This maybe related to having “/“ after collection name here:
.collection("events/")
Instead try this:
.collection("events")
Also it may be best to change child to collection here:
Reference firebaseStorageRef = FirebaseStorage.instance
.ref()
.child("events/")
Try to see if you get data back by running this:
itemCount: blogSnapshot.docs.length,
itemBuilder: (context, index) {
QuerySnapshot snap = blogSnapshot.data; // Snapshot
List<DocumentSnapshot> items = snap.documents; // List of Documents
DocumentSnapshot item = items[index]; Specific Document
return BlogTile(
organizer: item.data['Organizer'],
desc: item.data['desc'],
imgUrl: item.data['imgUrl'],
title: item.data['title'],
);
},
I think you need to utilize a QueryDocumentSnapshot to access the data in the document.

Provider not rebuilding on flutter

suddently from nowhere i came up with provider not re rendering my home page when it's updated. I've inspected it and it IS UPDATED. It has newer data when i change it in firebase but the UI won't re-render showing the new data. That's my code:
Main function
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:my_event_app/pages/HomePage/home_page.dart';
import 'package:my_event_app/pages/Login/login_page.dart';
import 'package:my_event_app/providers/User/user.dart';
import 'package:provider/provider.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => UserModel()),
],
child: MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData(
// is not restarted.
primarySwatch: Colors.blue,
),
home: const Wrapper(),
),
);
}
}
class Wrapper extends StatelessWidget {
const Wrapper({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return StreamBuilder<User?>(
stream: FirebaseAuth.instance.userChanges(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
User? user = snapshot.data;
if (user == null) {
return const LoginPage();
}
return StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('users')
.doc(FirebaseAuth.instance.currentUser!.uid)
.snapshots(),
builder: (context, userSnapshot) {
if (userSnapshot.hasData) {
Provider.of<UserModel>(context, listen: true)
.fromJson(userSnapshot.data!.data());
return const HomePage();
}
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
});
} else {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
);
}
},
);
}
}
And this is the home page:
import 'package:flutter/material.dart';
import 'package:my_event_app/http/auth/user/sign_out.dart';
import 'package:my_event_app/pages/Create_Event/create_event_page.dart';
import 'package:my_event_app/pages/Onboarding/onboarding_page.dart';
import 'package:my_event_app/providers/User/user.dart';
import 'package:my_event_app/widgets/event_card_widget.dart';
import 'package:provider/provider.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Consumer<UserModel>(builder: (context, user, child) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Icons.help_outline, color: Colors.black, size: 30),
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return const OnboardingPage();
}));
},
),
actions: [
IconButton(
icon: const Icon(
Icons.arrow_forward_ios_sharp,
color: Colors.black,
),
onPressed: () {
signOut();
},
),
],
elevation: 0,
backgroundColor: Colors.white,
),
backgroundColor: Colors.white,
body: SingleChildScrollView(
child: Container(
color: Colors.white,
padding: const EdgeInsets.all(16),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const CircleAvatar(
radius: 25,
backgroundImage: NetworkImage(
"https://cdnnmundo1.img.sputniknews.com/img/07e5/09/13/1116212032_100:0:1273:1173_1920x0_80_0_0_efb734331af13dfe11ff6d43293c60e2.png"),
),
Container(
height: 50,
width: 50,
decoration: BoxDecoration(
color: Colors.orange[400],
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
),
child: Center(
child: IconButton(
color: Colors.white,
onPressed: () {
// Navigate to add event widget
Navigator.push(context,
MaterialPageRoute(builder: (context) {
return const CreateEventPage();
}));
},
icon: const Icon(Icons.add),
),
),
),
],
),
const SizedBox(height: 32),
SizedBox(
width: double.infinity,
child: Text('Welcome, ${user.name}',
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
fontFamily: "Roboto")),
),
const SizedBox(height: 32),
Container(
padding: const EdgeInsets.all(16),
height: 100,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(10),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 5,
offset: const Offset(0, 3),
),
],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Stack(alignment: Alignment.center, children: [
SizedBox(
height: 45,
width: 45,
child: CircularProgressIndicator(
valueColor:
AlwaysStoppedAnimation(Colors.orange[400]),
value: 14 / 20,
semanticsValue: "14/20",
color: Colors.black,
),
),
const Text("78%",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
fontFamily: "Roboto")),
]),
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text("Weekly progress",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
)),
Text("14/20 tasks completed"),
],
),
const Icon(Icons.bar_chart),
],
),
),
Container(
margin: const EdgeInsets.symmetric(vertical: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const [
Text("You have 5 tasks for today",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
)),
Icon(Icons.calendar_today_outlined)
],
),
),
_renderEvents(user),
],
),
),
),
);
});
}
}
Column _renderEvents(UserModel user) {
return Column(
children: [
for (var event in user.events)
EventCard(
eventId: event,
),
],
);
}
And here's the provider:
import 'package:flutter/material.dart';
class UserModel extends ChangeNotifier {
String _name = '';
String _surnames = '';
String _uid = '';
String _email = '';
List<dynamic> _events = [];
String get name => _name;
String get surnames => _surnames;
String get uid => _uid;
String get email => _email;
List<dynamic> get events => _events;
UserModel();
set name(String value) {
_name = value;
notifyListeners();
}
set surnames(String value) {
_surnames = value;
notifyListeners();
}
set uid(String value) {
_uid = value;
notifyListeners();
}
set email(String value) {
_email = value;
notifyListeners();
}
set events(List<dynamic> value) {
_events = value;
notifyListeners();
}
void addEvent(String event) {
_events.add(event);
notifyListeners();
}
void removeEvent(String event) {
_events.remove(event);
notifyListeners();
}
void updateUser(String name, String uid) {
name = name;
uid = uid;
notifyListeners();
}
void clearUser() {
_name = '';
_uid = '';
notifyListeners();
}
Map<String, dynamic> toJson() {
return {
'name': _name,
'surnames': _surnames,
'uid': _uid,
'email': _email,
'events': _events
};
}
fromJson(Object? json) {
try {
Map<dynamic, dynamic> map = json as Map<dynamic, dynamic>;
_name = map['name'];
_surnames = map['surnames'];
_uid = map['uid'];
_email = map['email'];
_events = map['events'];
} catch (e) {
print(e);
}
}
}
```
As you can see i use Consumer in order to read data and i have a change notifier in the begginig, but it won't re render and show for example new name if i change it in fireabase.
Thank you so much!
You are using fromJson method to update values in UserModel, but it does not call notifyListeners. Add notifyListeners(); to the end of this method:
fromJson(Object? json) {
try {
Map<dynamic, dynamic> map = json as Map<dynamic, dynamic>;
_name = map['name'];
_surnames = map['surnames'];
_uid = map['uid'];
_email = map['email'];
_events = map['events'];
notifyListeners(); // add this
} catch (e) {
print(e);
}
}
Also some other things:
Consider declaring class UserModel with ChangeNotifier instead of class UserModel extends ChangeNotifier.
fromJson methods usually are acting as factory methods, meaning these return a new instance, and don't set members in an existing instance.
Instead of Provider.of<UserModel>(context, listen: true).fromJson(userSnapshot.data!.data()); you can try: context.read<UserModel>().fromJson(userSnapshot.data!.data());. Here you don't really need listening, you just want to find the provider and call fromJson. Your Consumer is the one which is listening to the changes accordingly.

Listview.Builder displays the the widget more than one time

I have two questions I hope you can help me with. I am building a listview.builder to loop through my array of objects and when I loop and display it displays the widget more than one time(photo is provided)
I am trying to iterate through my prefs of products to get the price of the product and quantity and add them to display the overall price, I tried forEach method but I couldn't quite figure out how.
Thanks for you help
class CheckOutCart extends StatefulWidget {
const CheckOutCart({Key? key}) : super(key: key);
#override
State<CheckOutCart> createState() => _CheckOutCartState();
}
class _CheckOutCartState extends State<CheckOutCart> {
late SharedPreferences sharedPrefs;
List<String>? cart;
// List<List<String ,int>> productsWithQuantity;
List productsWithQuantity = [];
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: _getPrefs(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
// return Text(productsWithQuantity[0][1]);
return buildContainer(productsWithQuantity);
}
return Center(
child: CircularProgressIndicator()); // or some other widget
},
);
}
Future<void> _getPrefs() async {
sharedPrefs = await SharedPreferences.getInstance();
cart = sharedPrefs.getStringList('userCart');
getProductsAsObj(cart);
}
Container buildContainer(productsWithQuantity) {
final Random random = new Random(5);
return Container(
padding: EdgeInsets.symmetric(
vertical: getProportionateScreenWidth(15),
horizontal: getProportionateScreenWidth(30),
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30), topRight: Radius.circular(30)),
boxShadow: [
BoxShadow(
offset: Offset(0, -15),
blurRadius: 20,
color: Color(0XFFDADADA).withOpacity(0.15),
),
],
),
child: SafeArea(
child: ListView.builder(
shrinkWrap: true,
itemCount: productsWithQuantity.length, //length of cart
itemBuilder: (context, index) => Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TotalPriceField(
titleText: "Merchandise Subtotal:\n",
priceText: productsWithQuantity[index][0].retail_price.toString(),
// priceText: productsWithQuantity.forEach((cart) => cart += cart[index][0].retail_price).toString()
// "\$375.5",
),
TotalPriceField(
titleText: "Shipping Total:\n",
priceText: "${random.nextInt(5)}",
),
],
),
SizedBox(
height: getProportionateScreenHeight(20),
),
TotalPriceField(
titleText: "Total Payment:\n",
priceText: "380.5",
),
SizedBox(
height: getProportionateScreenHeight(15),
),
SizedBox(
width: getProportionateScreenWidth(290),
child: DefaultButton(
text: "Check Out",
press: () {},
),
),
],
),
),
),
);
}
void getProductsAsObj(cart) {
for (var i = 0; i < cart.length; i++) {
var item = cart[i];
var items = item.split('-quantity-');
var product_ = items[0];
var quantity_ = items[1];
print(quantity_);
// product_ = '['+product_+']';
Map<String, dynamic> valueMap = json.decode(product_);
var product_obj = Product.fromMap(valueMap);
var itemx = [product_obj, quantity_];
productsWithQuantity.add(itemx);
}
}
}
```[![Listview.builder][1]][1]
[1]: https://i.stack.imgur.com/4wOyi.png