How to properly add user data using Bloc && How to properly use Google Places API - flutter

I'm having difficulties in two areas:
1) When a user successfully logs into their account using phone auth in Firestore, I take them to an "Edit profile" page so they can add their profile information. I get an error saying that I can't add data to a null user class or add data to a class within a class.
I currently have my user class setup something like the following:
class User {
String points;
Name name;
User({this.points, this.name});
}
class Name {
String firstName;
String lastName;
Name({this.firstName, this.lastName})
}
As you can see, I have a class within a class and when I try to add a value, it says I can't. I've tried doing it like
_bloc.user.name.firstName = value
And I've tried like
Name newName = Name();
newName.first = value.
The second one seems to work but it doesn't seem right. I'm hoping you could help me understand how to properly approach adding data for new users when I have a class within a class.
The second issue is understanding how to properly use the Places API. I'm currently learning from the below repo, but it's outdated and there's a couple lines I can't seem to figure out how to change. I also can't seem to find an updated tutorial since the October app crashing update.
https://github.com/alfianlosari/flutter_placez
Thanks in advance for your help!

Related

Saving to-do list items to be reviewed later?

I am extremely new to Flutter, so please forgive my ignorance and please explain things to me like I am a toddler.
I would like to implement a to-do list into my app similar to this project: https://github.com/ishrath-raji/todoey-flutter
It's just a basic list where users can add items, cross them out, and delete them. Very simple.
However, I have absolutely no idea how to take the items that users enter into the to-do list and store them in memory so that the user can review them later.
I've tried googling around, but all the answers I've seen are above my understanding and/or written in a way that is difficult to follow.
Any help would be very much appreciated!
I assume you have a view / page, where the user can give all the necessary information for the new ToDo item. This means you have a class representing a ToDoItem.
class ToDoItem {}
You will want to store them in some List.
As you probably want this list of ToDo items to be accessbible everywhere within the map, you should start researching the topic "state management".
As a starting point, just to name the easiest of all solutions, you could use Riverpod and declare one global variable:
final todoListRereference = StateProvider<List<ToDoItem>>((ref) => <ToDoItem>[]);
Now you have a list of ToDoItem which is accessible from everywhere in your app, provided you follow the steps to make Riverpod providers accessible everywhere. For example, in every build method you can use
final todoList = ref.watch(todoListRereference);
and you have access to all the stored ToDoItems.
In the case of your ToDoItem you can create with all the user information, you will have a construction like:
onPressed: () {
final todoItem = ToDoItem(...);
final todoListProvider = ref.read(todoListReference.notifier);
todoListProvider.state = [... todoListProvider.state, todoItem);
}
I just assumed it would happen after the user clicked something and the onPressed method of the according button is triggered.... However, first you create the ToDoItem. Then you access the List we made accessible with the reference. Then we change the "state" of that provider to a new state which is defined as all the old ToDoItems plus the newly created one.
If you have any pages in your app where you can see all the ToDoItems, you will now see one more.
I hope this is okay as a starting point.

Flutter Hive save custom object with list of custom objects gone after restarting app

I am using the Hive- Package in my project to store some data locally. That has been working fine so far, but now I am facing an issue:
I have a Custom-Class which also has a field with another Custom-Class:
part 'hive_vitals_interface.g.dart';
#HiveType(typeId: 1)
class HiveVitals extends HiveObject {
#HiveField(0)
String? id;
#HiveField(1)
DateTime? date;
#HiveField(2)
List<HiveDiscomfort> otherDiscomfort;
#HiveField(3)
List<HiveDiscomfort> mentalDiscomfort;
HiveVitals({
this.id,
this.date,
this.otherDiscomfort = const [],
this.mentalDiscomfort = const [],
});
}
And my HiveDiscomforts-Class:
part 'hive_discomfort_interface.g.dart';
#HiveType(typeId: 2)
class HiveDiscomfort extends HiveObject {
#HiveField(0)
String? title;
#HiveField(1)
int? intensity;
HiveDiscomfort({
this.title,
this.intensity,
});
}
I am trying to save HiveVitals like this:
static Future<void> addVitals(HiveVitals hiveVitals) async {
final vitalsBox = getVitalsBox();
await vitalsBox.put(hiveVitals.date!.toIso8601String(), hiveVitals);
}
And retrieve it like this:
static List<HiveVitals> getVitals() {
Box<HiveVitals> box = getVitalsBox();
List<HiveVitals> hiveVitals = box.values.toList();
return hiveVitals;
}
Problem:
I don't get any errors. In fact when saving my object and checking it in the debugger, everything is saved correctly. However when restarting the app, my List<HiveDiscomfort> fields are always empty again! But the rest of the HiveVitals-Fields are still saved correctly!?
What am I missing here? I don't get it... Any help is appreciated! Let me know if you need anything else!
Also opened an issue on Github.
I use this method and it works for me as List doesn't require registering an adapter:
await Hive.openBox<List>(bookmarks);
Add data like this:
boxValue.put(index, [
question.title,
question.options,
],
);
And you can access the data via ValueListenableBuilder.
If you're saying data is being saved and everything worked fine till you didn't restart the app. So the problem may be :
After restarting your app, you had may put a function that cleared all the data saved in Hive as soon as app starts.
Check this one.If like this will there then remove that line or function that clear all the data from hive DB.
Updated answer:
My previous solution got me thinking and I think I know why nested lists are not persisted.
It seems like hive is not checking for list equality and therefore never persist the changes, but uses the object as it is currently in memory. So, that is why as long as the application runs the object is correctly in memory, but when the app is closed hive does not persist the data as it thinks that the data (here the lists) never changed, even though they changed (this is my guess now without looking further into the code of the hive package).
So that means the solution would be to check for equality of the lists in the equals method. For this example it would be:
#override
bool operator ==(Object other) =>
identical(this, other) ||
other is HiveVitals &&
runtimeType == other.runtimeType &&
id == other.id &&
date == other.date &&
listEquals(otherDiscomfort, other.otherDiscomfort) &&
listEquals(mentalDiscomfort, other.mentalDiscomfort);
For me this solution works.
Old answer:
I had the same issue...
I try to explain my solution based on this example.
Given an object HiveVitals hiveVitals = HiveVitals(), whenever I tried to add something to the nested list of my custom object like hiveVitals.otherDiscomfort.add(), it was saved but not persisted (it was gone whenever I restarted the app). What I did was the following when I wanted to add something to the nested list:
List<HiveDiscomfort> tempList = [...hiveVitals.otherDiscomfort];
tempList.add(newData);
hiveVitals.otherDiscomfort = tempList;
That worked for me, now my data is persisted.
I think this is a problem with the package because I have the same issue that everything works okay but with restarting the app the data disappears. So I asked the question at hive flutter github and no answers yet. So I ask u to open an issue at hive flutter github to let them know that this is a real problem we face it.
Here are a couple of hints about the issue which may be why the data is lost:
Hive FAQ: What happens if my app is killed? The worst thing that can happen is
that you lose the last entry if it isn't written completely yet. Hive
has built-in integrity checking and crash recovery and takes care of
everything.
Limitations: Keys have to be 32 bit unsigned integers or ASCII Strings with a max
length of 255 chars. The supported integer values include all
integers between -2^53 and 2^53, and some integers with larger
magnitude Objects are not allowed to contain cycles. Hive will not
detect them and storing will result in an infinite loop. Only one
process can access a box at any time. Bad things happen otherwise.
Boxes are stored as files in the user's app-directory. Common illegal
characters/symbols such as /%& should therefore be avoided.
The most likely cause though may be related to improper implementation of the Hive Relationships behavior. Are you using HiveLists? If not look into this more closely. Secondly, you may just be trying to save too much when the app is killed. Try changing the save operation before the app is killed to verify proper behavior.

Can't access model class in second page in Flutter

I am trying to access a model class in the second page of my app.
In the first which I have named Main Activity I am able to call the class and write an updated value to it. My class is as follows:
class UserDetails{
String userName = "";
String userSurname = "";
}
In MainActivity I am able to call the above and update the userName and userSurname after reading from Firestore and print in the console:
UserDetails details = UserDetails();
details.userName = userName;
details.userSurname = userSurname;
print(details.userName);
print(details.userSurname);
When I move to the second page and try to call the same first two lines shown below I cannot even autocomplete the details.userName.
UserDetails details = UserDetails();
details.userName = userName;
The package is imported on both MainActivity and the second page. any idea why I cannot get UserDetails in the second? I thought maybe it is not re-usable across pages but even if I remove it from MainActivity it still doesnt allow the usage on the second page.
Essentially what I am trying to do is use userName and userSurname as global variables.
if the class is imported in both of your classes.
Run the command flutter clean. That would solve your problem.
I hope this helps.

Apache Isis: How to implement your custom submit form or page properly?

I'm new at Apache Isis and I'm stuck.
I want to create my own submit form with editable parameters for search some entities and a grid with search results below.
Firstly, I created #DomainObject(nature=Nature.VIEW_MODEL) with search results collection, parameters for search and #Action for search.
After deeper research, I found out strict implementations for actions (For exapmle ActionParametersFormPanel). Can I use #Action and edit #DomainObject properties(my search parameters for action) without prompts?
Can I implement it by layout.xml?
Then I tried to change a component as described here: 6.2 Replacing page elements, but I was confused which ComponentType and IModel should I use, maybe ComponentType.PARAMETERS and ActionModel or implement my own IModel for my case.
Should I implement my own Wicket page for search and register it by PageClassList interface, as described here: 6.3 Custom pages
As I understood I need to replace page class for one of PageType, but which one should I change?
So, the question is how to implement such issues properly? Which way should I choose?
Thank you!
===================== UPDATE ===================
I've implemented HomePageViewModel in this way:
#DomainObject(
nature = Nature.VIEW_MODEL,
objectType = "homepage.HomePageViewModel"
)
#Setter #Getter
public class HomePageViewModel {
private String id;
private String type;
public TranslatableString title() {
return TranslatableString.tr("My custom search");
}
public List<SimpleObject> getObjects() {
return simpleObjectRepository.listAll();
}
#Action
public HomePageViewModel search(
#ParameterLayout(named = "Id")
String id,
#ParameterLayout(named = "Type")
String type
){
setId(id);
setType(type);
// finding objects by entered parameters is not implemented yet
return this;
}
#javax.inject.Inject
SimpleObjectRepository simpleObjectRepository;
}
And it works in this way:
I want to implement a built-in-ViewModel action with parameters without any dialog windows, smth like this:
1) Is it possible to create smth like ActionParametersFormPanel based on ComponentType.PARAMETERS and ActionModel and use this component as #Action in my ViewModel?
2) Or I should use, as you said, ComponentType.COLLECTION_CONTENTS? As I inderstand my search result grid and my search input panel will be like ONE my stub component?
Thank you.
We have a JIRA ticket in our JIRA to implement a filterable/searchable component, but it hasn't yet made it to the top of the list for implementation.
As an alternative, you could have a view model that provides the parameters you want to filter on as properties, with a table underneath. (I see you asked another question here on SO re properties on view models, so perhaps you are moving in that direction also... I've answered that question).
If you do want to have a stab at implementing that ticket, then the ComponentTYpe to use is COLLECTION_CONTENTS. If you take a look at the isisaddons, eg for excel or gmap3 then it might help get you started.
======= UPDATE TO ANSWER (based on update made to query) ==========
I have some good news for you. v1.15.0-SNAPSHOT, which should be released in the couple of weeks, has support for "inline prompts". You should find these give a user experience very similar to what you are after, with no further work needed on your part.
To try it out, check out the current trunk, and then load the simpleapp (in examples/application/simpleapp). You should see that editing properties and invoking actions uses the new inline prompt style.
HTH
Dan

talend - name of components in tStatCatcher

I'm having trouble displaying the label of my components properly in tStatCatcher. I have renamed my components label but upon logging of tStatCatcher's origin field, the name is still the previous one.
E.g. Renamed my tDatabaseInput from MY_QUERY from tDatabaseInput1
tStatCatcher is still displaying tDatabaseInput1. It should be the new name MY_QUERY.
Anyone can provide assistance.
Thanks in advance
You can't delete the technical name of the component, it will always appear in logs as tComponent_1, to ensure unicity.
What you can do is adding MY_QUERY to the technical name, using __UNIQUE_NAME__
It will still not appear in your log, but you'll be able to see that MY_QUERY is linked to tComponent_1.
For example :
[]
I'm not sure if this is the best answer. But I'm sticking to this implementation for now unless someone shared a much better way.
I created a routine java class with a method that maps the from the tStatCatcher's row.origin to my hardcoded list of label names:
public static String mapToLabel(String uniqueName) {
switch(uniqueName) {
case "tDatabaseInput1":
return "MY_QUERY";
default:
return "--not mapped";
}
}
Then I called this method on my tMap's expression editor.