I tried to get data from firestore but display this error "The instance member 'mapRecords' can't be accessed in an initializer. " on Flutter - 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.

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 fetch data from firestore to chip widgets but then show "LateInitializationError". How I solve it?

I tried to fetch data from firestore to chip widgets but then show "LateInitializationError". And also chips should be can multi selection(select many chips). And also how to align 4 chips in a row like this example?I my code I think chips are show like ListView.
error..
I mean like this..
my code..
class uitry extends StatefulWidget {
const uitry({Key? key}) : super(key: key);
#override
State<uitry> createState() => _uitryState();
}
#override
Future<List<Words12>> fetchRecords() async {
var records = await FirebaseFirestore.instance.collection('12words').get();
return mapRecords(records);
}
List<Words12> mapRecords(QuerySnapshot<Map<String, dynamic>> records) {
var _list = records.docs
.map(
(words12) => Words12(
id: words12.id,
wordName: words12['wordName'],
categoryName: words12['categoryName'],
),
)
.toList();
return _list;
}
late int defaultChoiceIndex;
#override
void initState() {
initState();
defaultChoiceIndex = 0;
}
child: SizedBox(
width: width * 0.94,
height: height * 0.30,
child: FutureBuilder<List<Words12>>(
future: fetchRecords(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
List<Words12> data = snapshot.data ?? [];
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return (ChoiceChip(
label: Text(data[index].wordName),
selected: defaultChoiceIndex == index,
selectedColor: Colors.deepPurple,
onSelected: (value) {
setState(() {
defaultChoiceIndex =
value ? index : defaultChoiceIndex;
});
},
// backgroundColor: color,
elevation: 1,
padding: const EdgeInsets.symmetric(
horizontal: 5.0),
));
},
);
}
}),
),
#override
void initState() {
initState();
defaultChoiceIndex = 0;
}
Should be:
#override
void initState() {
super.initState();
defaultChoiceIndex = 0;
}
I believe it will initialize your defaultChoiceIndex then.
For the alignment of chips: Wrap your ChoiceChip in the ListView.builder in a Row(), with a mainAxisAlignment of your choosing:
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ChoiceChip(etc.),
],
),
I tried it .Now it working..
code
SizedBox(
width: width * 0.94,
height: height * 0.30,
child: Column(
children: <Widget>[
const SizedBox(height: 16),
Wrap(
children: hobbyList.map(
(hobby) {
bool isSelected = false;
if (selectedHobby!.contains(hobby)) {
isSelected = true;
}
return GestureDetector(
onTap: () {
if (!selectedHobby!.contains(hobby)) {
if (selectedHobby!.length < 50) {
selectedHobby!.add(hobby);
setState(() {});
print(selectedHobby);
}
} else {
selectedHobby!.removeWhere(
(element) => element == hobby);
setState(() {});
print(selectedHobby);
}
},
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('#F5F185')
: HexColor('#D9D9D9'),
borderRadius:
BorderRadius.circular(18),
border: Border.all(
color: isSelected
? HexColor('#F5F185')
: HexColor('#D9D9D9'),
width: 2)),
child: Text(
hobby,
style: TextStyle(
color: isSelected
? Colors.black
: Colors.black,
fontSize: 14,
fontWeight: FontWeight.w600),
),
),
),
);
},
).toList(),
),
],
),
),
class _uitryState extends State<uitry> {
List<String> hobbyList = [
'Shopping',
'Brunch',
'Music',
'Road Trips',
'Tea',
'Trivia',
'Comedy',
'Clubbing',
'Drinking',
'Wine',
];
List<String>? selectedHobby = [];

I tried to fetch data from firestore but in the console show empty array on flutter

I tried to fetch data from firestore to chips but the console showed an empty array. And when click chips colour change to blue colour.To fetch data I used model that's class name "Words12"
My collection name is "12words" at that collection have two fields "wordName"and "categoryName". I want display only "wordName" as chips
this..
I/flutter (14273): []
my full 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 uitry4 extends StatefulWidget {
const uitry4({Key? key}) : super(key: key);
#override
State<uitry4> createState() => _uitry4State();
}
class _uitry4State extends State<uitry4> {
//list
List<Words12> wordList = [];
//collection path
Future<List<Words12>> fetchRecords() 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((data) => Words12.fromJson(data.data())).toList();
for (var element in _wordList) {
print("name = ${element.wordName}");
}
print("length = ${_wordList.length}");
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),
FutureBuilder<List<Words12>>(
future: fetchRecords(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
wordList = snapshot.data ?? [];
return Wrap(
children: wordList.map(
(word) {
bool isSelected = false;
if (selectedWord!
.contains(word.wordName)) {
isSelected = true;
}
return GestureDetector(
onTap: () {
if (!selectedWord!
.contains(word.wordName)) {
if (selectedWord!.length < 50) {
selectedWord!.add(word.wordName);
deSelectedWord!.removeWhere(
(element) =>
element == word.wordName);
setState(() {});
print(selectedWord);
}
} else {
selectedWord!.removeWhere(
(element) =>
element == word.wordName);
deSelectedWord!.add(word.wordName);
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.wordName,
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 I get data from firestore?
Try change mapRecords() to this :
List<Words12> mapRecords(QuerySnapshot<Map<String, dynamic>> records) {
var _wordList = records.docs
.map(
(data) => Words12.fromJson(data.data())
)
.toList();
return _wordList;
}
and also change your if condition in your FutureBuilder:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
wordList = snapshot.data ?? []; //<--- change this
...
}
also change wordList to this:
class _uitry4State extends State<uitry4> {
List<Words12> wordList = []; //<--- change this
...
}
and this:
children: wordList.map(
(word) {
bool isSelected = false;
if (selectedWord!.contains(word.wordName)) {
isSelected = true;
}
return GestureDetector(
onTap: () {
if (!selectedWord!.contains(word.wordName)) {
if (selectedWord!.length < 50) {
selectedWord!.add(word.wordName);
deSelectedWord!.removeWhere(
(element) => element == word.wordName);
setState(() {});
print(selectedWord);
}
} else {
selectedWord!.removeWhere(
(element) => element == word.wordName);
deSelectedWord!.add(word.wordName);
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.wordName,
style: TextStyle(color: isSelected
? Colors.black
: Colors.black,
fontSize: 14,
fontWeight: FontWeight.w600),
),
),
).toList(),
also change your model class to this:
factory Words12.fromJson(Map<String, dynamic> json) => Words12(
id: json["id"] ?? "",
wordName: json["wordName"]?? "",
categoryName: json["categoryName"]?? "",
);
Just convert
List<Words12> mapRecords(QuerySnapshot<Map<String, dynamic>> records) {
var wordList = records.docs
.map(
(words12) => Words12(
id: words12.id,
wordName: words12['wordName'],
categoryName: words12['categoryName'],
),
)
.toList();
return wordList;
}
to
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;
}
and check what you get , also on a sidenote the way your using FutureBuilder is not ideal
Future _fetch = Future(() async {
var records = await FirebaseFirestore.instance.collection('12words').get();
return mapRecords(records);
})

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.

How to use index without an item builder in 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