I'm using back4app in my application and I have a class like this called Meal:
and this is my code snippet :
class EatenMeals with ChangeNotifier {
List<Meal> _eatenMeals = [];
List<Meal> get eatenMeals {
return [..._eatenMeals];
}
void addMeal(Meal meal) {
var newMeal = Meal(
id: meal.id,
cal: meal.cal,
catId: meal.catId,
title: meal.title,
duration: meal.duration,
affordability: meal.affordability,
imageUrl: meal.imageUrl,
ingredients: meal.ingredients,
isBreakfast: meal.isDinner,
isDinner: meal.isDinner,
isLunch: meal.isLunch,
steps: meal.steps);
_eatenMeals.add(newMeal);
}
}
Now I want to create a class that contain list of Meals object.
and attach to users how do I achieve this?
Checkout Parse Server Custom Objects. Here is an example for your case how to create a Custom Object for Meal.
class Meal extends ParseObject implements ParseCloneable {
Meal() : super(_keyTableName);
Meal.clone() : this();
/// Looks strangely hacky but due to Flutter not using reflection, we have to
/// mimic a clone
#override
clone(Map map) => Meal.clone()..fromJson(map);
/// Colum names
static const String _keyTableName = 'Meal';
static const String keyCatId = 'catId';
static const String keyTitle = 'title';
static const String keyImgUrl = 'imgUrl';
static const String keyIngredients = 'ingredients';
static const String keySteps = 'steps';
static const String keyCalorie = 'calorie';
static const String keyDuration = 'duration';
static const String keyAffordability = 'affordability';
static const String keyIsBreakfast = 'isBreakfast';
static const String keyIsLunch = 'isLunch';
static const String keyIsDinner = 'isDinner';
/// Getter & Setters
List<String> get catId => get<List<String>>(keyCatId);
set name(List<String> catId) => set<List<String>>(keyCatId, catId);
String get title => get<String>(keyTitle);
set title(String title) => set<String>(keyTitle, title);
Strin> get imgUrl => get<String>(keyImgUrl);
set imgUrl(String imgUrl) => set<String>(keyImgUrl, imgUrl);
List<String> get ingredients => get<List<String>>(keyIngredients);
set ingredients(List<String> ingredients) => set<List<String>>(keyIngredients, ingredients);
List<String> get steps => get<List<String>>(keySteps);
set steps(List<String> steps) => set<List<String>>(keySteps, steps);
num get calorie => get<num>(keyCalorie);
set calorie(num calorie) => set<num>(keyCalorie, calorie);
num get duration => get<num>(keyDuration);
set affordability(num duration) => set<num>(keyDuration, duration);
String get affordability => get<String>(keyAffordability);
set name(String affordability) => set<String>(keyAffordability, affordability);
bool get isBreakfast => get<bool>(keyIsBreakfast);
set isBreakfast(bool isBreakfast) => set<bool>(keyIsBreakfast, isBreakfast);
bool get isLunch => get<bool>(keyIsLunch);
set isLunch(bool isLunch) => set<bool>(keyIsLunch, isLunch);
bool get isDinner => get<bool>(keyIsDinner);
set isDinner(bool isDinner) => set<bool>(keyIsDinner, isDinner);
}
Then you have to register this subclass.
Parse().initialize(
...,
registeredSubClassMap: <String, ParseObjectConstructor>{
'Meal': () => Meal(),
},
);
Related
As you can see I have a list:
List avatarList = [
AssetsResources.VIP1,
AssetsResources.VIP2,
AssetsResources.VIP3,
AssetsResources.VIP4,
AssetsResources.VIP5,
AssetsResources.w1,
AssetsResources.w2,
];
I understand I can use method:
final bool isVIP = avatarList[index].contains('VIP');
But since AssetsResources.VIP1 is not a String like 'VIP1'but a path from other dart file, so here I have no idea how to check if the element from avatarList contains VIP value, thanks for any clue!
Update
Thanks guys for the help and sorry I didnt describe clearly, what I mean is, if
List idealList = [
'vip1',
'vip2',
'vip3',
'vip4',
'vip5',
];
so the elements in the idealList is 'vip1' but in my case the list myList is
List myList = [
AssetsResources.VIP1,
AssetsResources.VIP2,
AssetsResources.VIP3,
AssetsResources.VIP4,
AssetsResources.VIP5,
AssetsResources.w1,
AssetsResources.w2,
];
So it seems I can not directly use some methode as follows
final bool isVIP = myList[index].contains('VIP');
since the elements from myList is just a path(sorry I dont know how to call this value), could you please let me know in my case how to check if this path contains 'VIP' value? thanks!
Update
yes, AssetsResources is very simple, just store the asset path:
class AssetsResources {
/*worm avatar*/
static const String VIP1 = 'assets/worms/VIP_1.svg';
static const String VIP2 = 'assets/worms/VIP_2.svg';
static const String VIP3 = 'assets/worms/VIP_3.svg';
static const String VIP4 = 'assets/worms/VIP_4.svg';
}
The code should work fine :
class AssetsResources {
/*worm avatar*/
static const String VIP1 = 'assets/worms/VIP_1.svg';
static const String VIP2 = 'assets/worms/VIP_2.svg';
static const String VIP3 = 'assets/worms/VIP_3.svg';
static const String VIP4 = 'assets/worms/VIP_4.svg';
}
void main() {
List myList = [
AssetsResources.VIP1,
AssetsResources.VIP2,
AssetsResources.VIP3,
AssetsResources.VIP4,
];
for (final asset in myList) {
print(asset);
print(asset.contains('VIP'));
}
}
The above prints :
assets/worms/VIP_1.svg
true
assets/worms/VIP_2.svg
true
assets/worms/VIP_3.svg
true
assets/worms/VIP_4.svg
true
If I understood you correctly.
void main() {
for(var i = 0; i < avatarList.length; i++) {
String element = avatarList[i];
if(element.contains('VIP')) {
print(other.contains(element)); // true
print(other.firstWhere((e) => e.contains(element))); // 'VIP1', 'VIP2', 'VIP3', 'VIP4', 'VIP5'
}
}
}
List<String> avatarList = ['VIP1', 'VIP2', 'VIP3', 'VIP4', 'VIP5', 'w1', 'w2'];
List<String> other = ['VIP1', 'VIP2', 'VIP3', 'VIP4', 'VIP5', 'w1', 'w2'];
I'm working today on flutter - parse server project and to make a push notification system I had to upgrade the versions of the majority of my packages, after finishing stabilize the project I found that the plugin of parse sdk after the upgrade has too many problems.
First I found that when I want to get mu current user from the server I got allows null,
My code:
static Future<void> init() async {
await UserService.getUpdatedUser();
}
static Future<User> getUpdatedUser() async {
currentUser = await ParseUser.currentUser(customUserObject: User.clone());
if (currentUser?.objectId != null) await currentUser.getUpdatedUser();
return currentUser;
}
( I called it after the initialization, and it works fine before on parse 1.0.27)
Second and the biggest problem that every time I what to right into the server (using .save()) I got that error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception:
Stack Overflow
ParseObject._canbeSerialized package:parse_server_sdk/…/objects/parse_object.dart:222
ParseObject._canbeSerialized package:parse_server_sdk/…/objects/parse_object.dart:234
ParseObject._canbeSerialized package:parse_server_sdk/…/objects/parse_object.dart:245 ...
ParseObject._canbeSerialized (p
Really I didn't know how to solve it whole the project now has many errors. (I can't return to 1.0.27 or 2.0.0 because I'm using dio ^4.0.0 and it didn't support it :( )
Update:
my user class:
class User extends ParseUser implements ParseCloneable {
User(String username, String password, String emailAddress)
: super(username, password, emailAddress);
User.clone() : this(null, null, null);
#override
User clone(Map<String, dynamic> map) => User.clone()..fromJson(map);
static const String nameKey = 'name';
static const String surnameKey = 'surname';
static const String phoneKey = 'phone';
static const String cinKey = 'cin';
static const String dobKey = 'dob';
static const String positionKey = 'position';
static const String useModeKey = 'useMode';
static const String isLookingKey = 'isLooking';
static const String driverKey = 'driver';
static const String adminKey = 'admin';
static const String creditCardKey = 'creditCard';
static const String isSubscribedKey = 'isSubscribed';
static const String finalSubscribeDateKey = 'finalSubscribeDate';
static const String isDriverKey = 'isDriver';
static const String countryCodeKey = 'countryCode';
static const String partnerKey = 'partner';
String get name => get<String>(nameKey);
String get surname => get<String>(surnameKey);
DateTime get dob => get<DateTime>(dobKey);
String get phone => get<String>(phoneKey);
String get cin => get<String>(cinKey);
num get useMode => get<num>(useModeKey);
bool get isLooking => get<bool>(isLookingKey);
Driver get driver =>
Driver().clone(get<ParseObject>(driverKey)?.toJson(full: true));
String get creditCard => get<String>(creditCardKey);
bool get isSubscribed => get<bool>(isSubscribedKey);
DateTime get finalSubscribeDate => get<DateTime>(finalSubscribeDateKey);
String get countryCode => get<String>(countryCodeKey);
Partner get partner =>
Partner().clone(get<ParseObject>(partnerKey)?.toJson(full: true));
set name(String value) => set<String>(nameKey, value);
set surname(String value) => set<String>(surnameKey, value);
set dob(DateTime dob) =>
set<dynamic>(dobKey, {"__type": "Date", "iso": "$dob"});
set phone(String value) => set<String>(phoneKey, value);
set cin(String value) => set<String>(cinKey, value);
set useMode(num value) => set<num>(useModeKey, value);
set isLooking(bool value) => set<bool>(isLookingKey, value);
set driver(Driver value) => set<Driver>(driverKey, value);
set creditCard(String value) => set<String>(creditCardKey, value);
set isSubscribed(bool value) => set<bool>(isSubscribedKey, value);
set finalSubscribeDate(DateTime finalSubscribeDate) => set<dynamic>(
finalSubscribeDateKey, {"__type": "Date", "iso": "$finalSubscribeDate"});
set isDriver(bool value) => set<bool>(isDriverKey, value);
set countryCode(String value) => set<String>(countryCodeKey, value);
set partner(dynamic value) => set<dynamic>(partnerKey, value);
ParseGeoPoint get position => get<ParseGeoPoint>(positionKey);
set position(ParseGeoPoint value) => set<ParseGeoPoint>(positionKey, value);
String get fullname => '$name $surname';
String get isVerifiedMsg =>
emailVerified ?? false ? '' : '(' + 'isVerified'.tr + ')';
bool get isDriver => driver?.objectId != null;
static User fromParseUser(ParseUser parseUser) {
if (parseUser?.objectId == null) return null;
final user = User(
parseUser.username, parseUser.password, parseUser.emailAddress)
..objectId = parseUser.objectId
..set(User.nameKey, parseUser.get(User.nameKey))
..set(User.surnameKey, parseUser.get(User.surnameKey))
..set(User.phoneKey, parseUser.get(User.phoneKey))
..set(User.cinKey, parseUser.get(User.cinKey))
..set(User.dobKey, parseUser.get(User.dobKey))
..set(User.positionKey, parseUser.get(User.positionKey))
..set(User.useModeKey, parseUser.get(User.useModeKey))
..set(User.isLookingKey, parseUser.get(User.isLookingKey))
..set(User.isSubscribedKey, parseUser.get(User.isSubscribedKey))
..set(
User.finalSubscribeDateKey, parseUser.get(User.finalSubscribeDateKey))
..set(User.driverKey, Driver.parse(parseUser.get(User.driverKey)))
..set(User.countryCodeKey, parseUser.get(User.countryCodeKey));
/* ..set(User.partnerKey,
Partner.parse(parseUser.get(User.partnerKey))));*/
/* if(user?.driver != null) {
final driver = Driver.parse(user.get(User.driverKey));
user.set(User.driverKey, driver);
} */
return user;
}
}
I was wondering if I can check which constructor I used to create the created element in an if statement in dart.
A simple example of what I want to do:
class Employee {
int id;
String name;
String title;
Employee.id(this.id);
Employee.name(this.name);
Employee.title(this.title);
}
Now I have an if statement somewhere in my code and want to check if I used the constructor Employee.id. In this case I would do something, somehow like this:
Employee e = new Employee.id(1)
//check if e was created with Employee.id constructur
if (e == Emploee.id) {
print(e.id)
} else {
print("no id")
}
Is there a way to do this? Thank you for your answer.
You can make your class a Union type using the freezed package and use the folding methods as shown below to see what constructor was used:
import 'package:freezed_annotation/freezed_annotation.dart';
part 'tst.freezed.dart';
#freezed
abstract class Employee with _$Employee {
const factory Employee.id(int id) = IdEmployee;
const factory Employee.name(String name) = NameEmployee;
const factory Employee.title(String title) = TitleEmployee;
}
void main() {
Employee employee1 = Employee.id(0);
Employee employee2 = Employee.name('some name');
Employee employee3 = Employee.title('some title');
employee1.when(
id: (int id) => print('created using id contsrutor and id= $id'),
name: (String name) => print('created using name const and name = $name'),
title: (String title)=>print('created using title const and title = $title'),
);//prints the first statement
employee2.when(
id: (int id) => print('created using id contsrutor and id= $id'),
name: (String name) => print('created using name const and name = $name'),
title: (String title)=>print('created using title const and title = $title'),
);//prints the second statement
employee3.when(
id: (int id) => print('created using id contsrutor and id= $id'),
name: (String name) => print('created using name const and name = $name'),
title: (String title)=>print('created using title const and title = $title'),
);//prints the third statement
print(employee1 is IdEmployee);
print(employee1 is NameEmployee);
}
and the output will be:
created using id contsrutor and id= 0
created using name const and name = some name
created using title const and title = some title
true
false
You can define private enum property for you to set private info like this, and print it with a function later on. Also don't forget to mark your constructors with factory.
enum _ConstructorType {
Identifier,
Name,
Title,
}
class Employee {
int id;
String name;
String title;
_ConstructorType _constructorType;
factory Employee.id(id) {
return Employee._privateConstructor(_ConstructorType.Identifier, id: id);
}
factory Employee.name(name) {
return Employee._privateConstructor(_ConstructorType.Name, name: name);
}
factory Employee.title(title) {
return Employee._privateConstructor(_ConstructorType.Title, title: title);
}
Employee._privateConstructor(this._constructorType,
{this.id, this.name, this.title});
String constructorDescription() {
return this._constructorType.toString();
}
}
If you need this information not as a string, but as enum, you can always remove underscore on it, and make this info public for you to use outside of the class.
i want to do use the model's properties such as:
Animal.id as a param to a function or use some extension method to be able to "id". similarly, i'd like to use Animal.title in that way to get "title" as a returned value. how could i do this with my class to get a string for any given property name?
int _id;
String _title;
Animal(this._id, this._title);
int get id => _id;
String get title => _title;
}
the usage case is being able to query without having autocomplete on my model's property names in a string for sql querying:
List<Map> results = await db.query("Animal",
columns: Set. ["id", "title"],
where: 'id = ?',
whereArgs: [id]);
Using the dart:mirrors package you can dynamically access your class properties and invoke methods using their string names.
https://api.dart.dev/stable/2.4.0/dart-mirrors/dart-mirrors-library.html
import 'dart:mirrors';
class Animal {
int _id;
String _title;
Animal(this._id, this._title);
int get id => _id;
String get title => _title;
}
main() {
var r = reflect(Animal(1, 'Dog'));
print(r.getField(Symbol('id')).reflectee);
print(r.getField(Symbol('title')).reflectee);
}
import 'dart:mirrors';
class MyClass {
int i, j;
void my_method() { }
int sum() => i + j;
MyClass(this.i, this.j);
static noise() => 42;
static var s;
}
main() {
MyClass myClass = new MyClass(3, 4);
InstanceMirror myClassInstanceMirror = reflect(myClass);
ClassMirror MyClassMirror = myClassInstanceMirror.type;
InstanceMirror res = myClassInstanceMirror.invoke(#sum, []);
print('sum = ${res.reflectee}');
var f = MyClassMirror.invoke(#noise, []);
print('noise = $f');
print('\nMethods:');
Iterable<DeclarationMirror> decls =
MyClassMirror.declarations.values.where(
(dm) => dm is MethodMirror && dm.isRegularMethod);
decls.forEach((MethodMirror mm) {
print(MirrorSystem.getName(mm.simpleName));
});
print('\nAll declarations:');
for (var k in MyClassMirror.declarations.keys) {
print(MirrorSystem.getName(k));
}
MyClassMirror.setField(#s, 91);
print(MyClass.s);
}
the output:
sum = 7
noise = InstanceMirror on 42
Methods:
my_method
sum
noise
All declarations:
i
j
s
my_method
sum
noise
MyClass
91
I've written a class like this,
class LessonCategory{final String name;
LessonCategory(this.name);
#override
String toString() {
return 'LessonCategory{name: $name}';
}
}
class Lessons {
final String lessonsName;
int discontinuity;
final LessonCategory lesscategory;
Lessons(this.lessonsName, this.discontinuity,
this.lesscategory,
);
#override
String toString() {
return 'Lessons{lessonsName: $lessonsName, discontinuity:
$discontinuity, lesscategory: $lesscategory}';
}
}
class Data {
static List<LessonCategory> categories = [
LessonCategory("a1"),
];
static List<Lessons> lessons = [
Lessons(
'Lesson A1',
0,
getCategoryFromName("a1"),
),
];
static LessonCategory getCategoryFromName(name) {
return categories.firstWhere(
(c) => c.name.toLowerCase() == name.toString().toLowerCase());
}
}
But I can't figure out how to add a new element.I already tried add,push,insert (or i missed something).
Can someone please show me the right way?
i want something like
Data.lessons.add({
lessonsName: 'Lesson Z1',
discontinuity: 0
lessCategory: 'a1'
});
just remove static syntax. if it is defined as static, it will be immutable
class Data {
static List<LessonCategory> categories = [
LessonCategory("a1"),
];
List<Lessons> lessons = [ // Remove Static syntax
Lessons(
'Lesson A1',
0,
getCategoryFromName("a1"),
),
];
static LessonCategory getCategoryFromName(name) {
return categories.firstWhere(
(c) => c.name.toLowerCase() == name.toString().toLowerCase());
}
}
but also we can correct another syntaxes
Data newData = Data();
newData.lessons.add(Lessons(
'Lesson Z1', // remove named parameters, and use positional params
0,
LessonCategory('a1'),
));
print("New Length : ${newData.lessons.length}");
Fully working code
class LessonCategory {
final String name;
LessonCategory(this.name);
#override
String toString() {
return 'LessonCategory{name: $name}';
}
}
class Lessons {
final String lessonsName;
int discontinuity;
final LessonCategory lesscategory;
Lessons(
this.lessonsName,
this.discontinuity,
this.lesscategory,
);
#override
String toString() {
return """Lessons{lessonsName: $lessonsName, discontinuity: $discontinuity, lesscategory: $lesscategory}""";
}
}
class Data {
static List<LessonCategory> categories = [
LessonCategory("a1"),
];
List<Lessons> lessons = [ // Remove Static syntax
Lessons(
'Lesson A1',
0,
getCategoryFromName("a1"),
),
];
static LessonCategory getCategoryFromName(name) {
return categories.firstWhere(
(c) => c.name.toLowerCase() == name.toString().toLowerCase());
}
#override
String toString() {
return "{${lessons.map((fruit) => print(fruit))}}";
}
}
main(List<String> args) {
Data newData = Data(); // Create instance first
newData.lessons.add(Lessons(
'Lesson Z1', // remove named parameters, and use positional params
0,
LessonCategory('a1'),
));
print("New Length : ${newData.lessons.length}");
newData.lessons.add(Lessons(
'Lesson Z1',
0,
LessonCategory('a1'),
));
print("New Length : ${newData.lessons.length}");
print("${newData.lessons}");
}
which we able to play arount in Dartpad
Result
remove the static syntax and the problem will be solved