I've created a map yet am having difficulty accessing the variable 'contact' within a stateful widget. I'm not sure where else to declare final Contact contact; .
The Contact model file.
class Contact {
int rating;
String name;
String location;
int phoneNumber;
String instagram;
int birthday;
String notes;
Contact(this.name, this.phoneNumber, this.location, this.rating,
this.instagram, this.birthday, this.notes);
Map<String, dynamic> toJson() => {
'Name': name,
'PhoneNumber': phoneNumber,
'Location': location,
'Rating': rating,
'Instagram': instagram,
'Birthday': birthday,
'Notes': notes,
};
Where final Contact contact; is currently declared
class NewContact extends StatefulWidget {
NewContact({Key key, #required this.contact}) : super(key: key);
final Contact contact;
#override
NewContactState createState() => NewContactState();
}
class NewContactState<T extends NewContact> extends State<T> {
final db = FirebaseFirestore.instance; //...etc
Where the Map is being called
await db
.collection("userData")
.doc(uid)
.collection("Contacts")
.add(contact.toJson());
Error = Undefined name 'contact'.
Since contact is defined in the class that extends statful widget, NewContact, and you want to access it's corresponding state class NewContactState, you should call it like this widget.contact.toJson().
Related
I have 2 object stored in Firestore Product & Shop
And there maybe a lot of Product and Shop in the future, so I have Shop DocumentReference in Product and vise-versa
Here are how they look like
class Shop extends Equatable {
final String? id;
final String name;
final List<Product?> shopProduct;
final DateTime createDate;
...
static Future<Shop> fromDocument(DocumentSnapshot doc) async {
final data = doc.data() as Map<String, dynamic>;
final shopProductRef = data['shopProduct'];
final List<Product?> shopProductList;
if (shopProductRef.isNotEmpty) {
shopProductList = List.from(shopProductRef.map((ref) async {
Product.fromDocument(await ref!.get());
}));
} else {
shopProductList = [];
}
return Shop(
id: doc.id,
name: data['name'],
shopProduct: shopProductList,
createDate: (data['createDate'] as Timestamp).toDate(),
);
}
And
class Product extends Equatable {
final String? id;
final Shop shop;
final double price;
final String title;
final DateTime date;
...
static Future<Product?> fromDocument(DocumentSnapshot doc) async {
final data = doc.data() as Map<String, dynamic>;
final shopRef = data['shop'] as DocumentReference;
final shopDoc = await shopRef.get();
return Product(
id: doc.id,
shop: await Shop.fromDocument(shopDoc),
price: data['price'],
title: data['title'],
date: (data['date'] as Timestamp).toDate(),
);
}
This is what I think should work in the first place but it brings up a problem that it is causing a loop since both are referencing each other.
I have come up a fix which is creating a second fromDocument method which skip the shopProduct or Shop when I am referencing it.
Is it the only / best way to do it?
Thank you
As I know you have two options
First one is to add a document reference instead of referring to the classes
something like this
class Product extends Equatable {
final String? id;
final DocumentRefrence<Shop> shop;
final double price;
final String title;
final DateTime date;
...
and also do the same for Shop model
class Shop extends Equatable {
final String? id;
final String name;
final List<DocumentReference<Product>?> shopProduct;
final DateTime createDate;
...
Second one is as you mentioned, create a method for Product model and name it for example: Map<String, dynamic> toShopCollection() and use it while setting a shop in firestore and also do the same for Shop model.
cm if you need more details
I have the next map config, I was wondering how I could access to it using the #JsonKey keyword.
import 'package:json_annotation/json_annotation.dart';
part 'user_model.g.dart';
#JsonSerializable()
class UserModel {
#JsonKey(name: 'username')
String username;
#JsonKey(name: 'realName')
String realname;
#JsonKey(name: 'gender')
String gender;
#JsonKey(name: 'date_birth')
String dateBirth;
#JsonKey(name: 'isObserver')
bool isObserver;
#JsonKey(name: 'friends')
List<dynamic> friendsList;
#JsonKey(name: 'pendingFriends')
List<dynamic> pendingFriendsList;
#JsonKey(name: 'config') // Here, config is a map, how can I access to their data?
bool notifyFriend;
UserModel(this.username, this.realname, this.dateBirth, this.gender,
this.isObserver, this.friendsList, this.pendingFriendsList, this.notifyFriend);
factory UserModel.fromJson(Map<String, dynamic> json) =>
_$UserModelFromJson(json);
Map<String, dynamic> toJson() => _$UserModelToJson(this);
}
First of all you have to create another class with the name config having those 3 variables in it and then import that class in this class and replace the variable there with that like :
class Config{
#JsonKey(name: 'notifyFriends')
bool notifyFriend;
#JsonKey(name: 'recordAudio')
bool recordAudio;
#JsonKey(name: 'sendTweet')
bool sendTweet;
Config(this.sendTweet, this.recordAudio, this.notifyFriend);
factory Config.fromJson(Map<String, dynamic> json) =>
_$ConfigFromJson(json);
Map<String, dynamic> toJson() => _$ConfigToJson(this);
}
and use it like this:
#JsonKey(name: 'config') // Here,
Config config;
I hope this clear your problem.
Hi I'am new to Flutter making an app for booking appointments which require to screens for two types of users i.e. patient and doctor.
class DashboardPage extends StatefulWidget {
#override
_DashboardPageState createState() => _DashboardPageState();
}
class _DashboardPageState extends State<DashboardPage> {
UserProvider userProvider;
final AuthMethods _authMethods = AuthMethods();
#override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) async {
userProvider = Provider.of<UserProvider>(context, listen: false);
await userProvider.refreshUser();
_authMethods. getUserDetails();
});
}
User user = User();
#override
Widget build(BuildContext context) {
if (user.role == 'patient') {
return PatientHomePage();
}
else if (user.role == 'doctor') {
return DoctorHomePage();}
return Container(color: Colors.red,);
}
}
role variable is defined in another dart file:
class User { String uid; String name; String email; String role = "patient"; String profilePhoto; User({ this.uid, this.name, this.email, this.role, this.profilePhoto, }); ........... }
the default value "patient" is assigned to it when a user logs in. Future<void> addDataToDb(FirebaseUser currentUser) async { User user = User( uid: currentUser.uid, email: currentUser.email, name: currentUser.displayName, profilePhoto: currentUser.photoUrl, role: "patient"); firestore .collection(USERS_COLLECTION) .document(currentUser.uid) .setData(user.toMap(user)); } all this is happening in another dart file
But this logic is not working as expected as it's showing only the red screen on phone which implies that
there is some issue in getting user.role from firebase.
Please help me...
class DashboardPage extends StatefulWidget {
#override
_DashboardPageState createState() => _DashboardPageState();
}
class _DashboardPageState extends State<DashboardPage> {
UserProvider userProvider;
final AuthMethods _authMethods = AuthMethods();
User user = User();
#override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) async {
userProvider = Provider.of<UserProvider>(context, listen: false);
/// This method is future method so it might happen that after widget render you are getting response.
await userProvider.refreshUser();
/// seState will rebuild your widget with new user details
setState(() {
user = _authMethods. getUserDetails();
});
});
}
#override
Widget build(BuildContext context) {
if (user.role == 'patient') {
return PatientHomePage();
}
else if (user.role == 'doctor') {
return DoctorHomePage();}
return Container(color: Colors.red,);
}
}
I am trying to fill my CurrentUser object with the same information as the uid of the logged in user when my users login to the application
My databaseService :
final CollectionReference userCollection =
Firestore.instance.collection('users');
Future<User> getCurrentUserData(String uid) async{
var doc = userCollection.document(uid);
And My Home Page :
class HomeScreen extends StatefulWidget {
final FirebaseUser currentUser;
HomeScreen({#required this.currentUser});
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
And My CurrentUser Model :
class CurrentUser {
static String name;
static String lastName;
static String uid;
static String phone;
static String addresses;
static String photoString;
static int cityId;
static int districtId;
static List<Loss> userLosses;
}
But i cant figure out connect them
If you are using the firebase authentication then you can use FiresbaseAuth.instance.currentUser, it will return a FirebaseUser object that will contain the info of the current user.
I figure it like this:
Future<User> getCurrentUserData(String uid)async {
var docRef = await userCollection.document(uid).get();
User currentUser = User.fromJson(docRef.data);
currentUser.uid=docRef.documentID;
return currentUser;
}
docRef.data is <String,dynamic> map and just i change my user class like this:
factory User.fromJson(Map<String, dynamic> json) {
return User(
name: json['Name'].toString(),
lastName: json['LastName'].toString(),
phone: json['Phone'].toString(),
photoString: json['PhotoString'].toString(),
districtId: int.parse(json['DistrictId'].toString()),
cityId: int.parse(json['CityId'].toString()),
addresses: json['Addresess'].toString());
}
I want to declare a user object, that I will instantiate with an http request, and I want it to be global. How can I do it? With a Singleton? But how can I make this class also a Singleton? Or is there another way?
That is what I've done so far:
class User{
String username;
String password;
int id;
User({this.username, this.id});
factory User.fromJson(Map<String, dynamic> json){
return User(
username: json['name'],
id: json['id']
);
}
}
and then:
var user = await login(username, password, context);
In flutter, you should not make singletons. Instead, you should store it into a widget that exposes these data to all of its descendants.
Usually InheritedWidget
The reason being, with such architecture all the descendants are automatically aware of any change made to your "singleton".
A typical example would be the following:
#immutable
class User {
final String name;
User({this.name});
}
class Authentificator extends StatefulWidget {
static User currentUser(BuildContext context) {
final _AuthentificatorScope scope = context.inheritFromWidgetOfExactType(_AuthentificatorScope);
return scope.user;
}
final Widget child;
Authentificator({this.child, Key key}): super(key: key);
#override
_AuthentificatorState createState() => _AuthentificatorState();
}
class _AuthentificatorState extends State<Authentificator> {
#override
Widget build(BuildContext context) {
return _AuthentificatorScope(
child: widget.child,
);
}
}
class _AuthentificatorScope extends InheritedWidget {
final User user;
_AuthentificatorScope({this.user, Widget child, Key key}) : super(child: child, key: key);
#override
bool updateShouldNotify(_AuthentificatorScope oldWidget) {
return user != oldWidget.user;
}
}
which you have to instantiate like this:
new MaterialApp(
title: 'Flutter Demo',
builder: (context, child) {
return Authentificator(
child: child,
);
},
home: Home(),
);
and then use inside your pages like this:
#override
Widget build(BuildContext context) {
User user = Authentificator.currentUser(context);
...
}