Access an object from another dart file - dart

I have an object Students on Group1.dart file
class Group1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
//...
Students('Alex','Thomas')
//...
}
//My Object
Students (String a, string b){
//....
}
}
And I create Group2.dart and Group3.dart.
My question, how can I access object Students from Group1 ?
Like that
class Group2 extends StatelessWidget {
#override
Widget build(BuildContext context) {
//...
Students('Alex','Thomas')
//...
}
}
I tried create Students.dart
class ModalStudents {
String _a, _b;
ModalStudents (this._a, this._b);
String get a => _a;
String get b =>_b;}
but I don't know what next.

If I correctly understood your question, then you want to share "state". In this case your Students object. There are many state management patterns like:
ScopedModel
Redux
BLoC
...
Then you can do whatever you want with your Students in every class :)
Other scenario: Your Widget Group2 is in Group1. Then you can just pass it as parameter ;)
Yours Glup3

You can use the scoped_model package
You want the model to extend Model
class StudentModel extends Model {
...
}
In group 1
Widget build(BuildContext context) {
return new ScopedModel<StudentModel>(
model: StudentModel(),
In group 2
ScopedModelDescendant<StudentModel>(
builder: (context, child, model){
...
}
Inside the descendant you can access the properties of the model like such: model.a, model.b

Related

Flutter unable to set state of list<object>

Here is how the main TodoApp widget looks like:
class TodoApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(title: 'Todo List', home: new TodoList());
}
}
I have created a class for a list item which is called Task:
class Task {
String name;
int number;
Task(this.name, this.number);
}
The list widget looks like this:
class TodoList extends StatefulWidget {
#override
createState() => new TodoListState();
}
The TodoListState class has a method which adds new items to the list:
class TodoListState extends State<TodoList> {
List<Task> _todoItems = [];
List<bool> checkedItems = []; // this was created for testing purposes
void _addTodoItem(Task task) {
if (task.name.length > 0) {
setState(() => checkedItems.add(false)); // works fine
setState(() => _todoItems.add(new Task('abc', 12))); // does not work
}
}
...
}
Why when _addTodoItem method is called, one item is added to the checkedItems list but _todoItems list is left unchanged? What am I missing?
It's working as it should, setState is only called once, hence the first method is executed. You should add both methods in the setState method, since it's called once per run or state, you can write it like this:
....
setState(() => {
checkedItems.add(false);
_todoItems.add(new Task('abc', 12);
});
....

How to access Stateful widget variable inside State class outside the build method?

I am trying to access the 'updateNotesModel' variable declared in the code in the _UpdateNotesState. I found out that you can do it using the 'widget' keyword as shown in the Scaffold below. But the problem here is that I am trying to access the variable outside the build method in order to give the TextEditingController a default value. How can I achieve this?
class UpdateNotes extends StatefulWidget {
final NotesModel updateNotesModel;
UpdateNotes({Key key, this.updateNotesModel}): super(key: key);
#override
_UpdateNotesState createState() => _UpdateNotesState();
}
class _UpdateNotesState extends State<UpdateNotes> {
TextEditingController _titleController =
new TextEditingController(text: widget.updateNotesModel.someValue); //getting an error
}
#override
Widget build(BuildContext context) {
return Scaffold(
var a = widget.updateNotesModel.someValue
.
.
.
)
}
}
You can do it in initState:
class _UpdateNotesState extends State<UpdateNotes> {
TextEditingController _titleController = new TextEditingController();
#override
void initState() {
_titleController.text= widget.updateNotesModel.someValue;
super.initState();
}
}
Now you can use the late keyword. From the docs:
Dart 2.12 added the late modifier, which has two use cases:
Declaring a non-nullable variable that’s initialized after its declaration.
Lazily initializing a variable.
class _UpdateNotesState extends State<UpdateNotes> {
late TextEditingController _titleController = new TextEditingController(text: widget.updateNotesModel.someValue);
#override
Widget build(BuildContext context) {
.
.
.
}
}
that unfortunately cannot be done as, widget keyword cannot be accessed while initializing

ScopedModelDescendant String returns null. Not retrieving state

I am refactor app to use scoped_model but have issue. State not seem to be pass correct between widget.
I am start with add ScopedModel to top of widget tree on startup.:
#override
Widget build(BuildContext context) {
UserModel().initialiseValues();
return ScopedModel<UserModel>(
model: UserModel(),
child: MaterialApp(
home: new Page(),
),
);
}
This call .initialiseValues(); so the model read from SharedPreferences and store in variables:
class UserModel extends Model {
String _name;
String get name => _name;
void initialiseValues() async {
SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
_name = sharedPrefs.getString('name');
print(‘_name from sharedPrefs is $_name');
print(‘name from sharedPrefs is $name');
notifyListeners();
}
}
Both print statement return correct name.
But when I try call using ScopedModelDescendant in another page name return null:
class PageFive extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ScopedModelDescendant<UserModel>(
builder: (context, child, model) =>
Text('${model.name}'),
);
}
}
Text('${model.name}'), return null
Anyone know why name return null?
I have look hard for solve but no idea why.
There seems to be two problems:
1.- You are calling .initialiseValues() in a static way when the method is not static. And then you are creating a new diferent UserModel inside the ScopedModel.
2.- You are calling an async function inside the first build() method but you are not certain when it is going to finish and possibly, the UserModel is not fully initialized when building the tree.
You should maybe have a boolean variable (or check the .name for null) and set it to true when initialized.
In the build method, if that variable is false you could return a CircularProgressIndicator and when true just return your widget.
#override
Widget build(BuildContext context) {
var userModel = UserModel()..initialiseValues();
return ScopedModel<UserModel>(
model: userModel,
child: MaterialApp(
home: new Page(),
),
);
}
class PageFive extends StatelessWidget {
#override
Widget build(BuildContext context) {
return ScopedModelDescendant<UserModel>(
builder: (context, child, model) {
if (model.name == null)
return CircularProgressIndicator();
else
return Text('${model.name}');
});
}
}

createState method not always called when creating new StatefulWidget

I have a collection of simple objets that sometimes changes. I am using a ListView to render those objects, basically text. When my collection changes the list is rebuild with the new objects, so if the list changes from 1 to 3 items, I see 3 items, but the first one keeps its previous value.
I've noticed that the method "createState" is not called in all cases when I create a new CustomTextField (in the example above, it is called only when new elements are added to the list).
How do I make sure my list is updated properly when my collection changes?
My parent widget builds a list of text fields:
...
#override
Widget build(BuildContext context) {
...
var list = <Widget>[];
collection.forEach((item) {
var widget = CustomTextField(
content: item,
);
list.add(widget);
...
return new ListView(
children: list,
);
});
...
My CustomTextField definition:
class CustomTextField extends StatefulWidget {
final MediaContent content;
CustomTextField({
Key key,
this.content,
}) : super(key: key);
#override
CustomTextFieldState createState() {
return CustomTextFieldState();
}
}
...
MediaContent is a very simple object containing some text:
class MediaContent {
String textData;
ContentType type;
MediaContent(
this.type,
);
}
You have to define unique Key for you collections items, take a look at here:
https://www.youtube.com/watch?v=kn0EOS-ZiIc

Flutter and Firestore: How can access variables from Stateful Widget to create a new document?

i want to use a final variable from a StatefulWidget inside a StatelessWidget to create a new document in Firestore.
But i get always the same issue: Only static members can be accessed in initializers
My StatefulWidget Code:
class UserProfile extends StatefulWidget {
UserProfile({this.auth, this.onSignedOut, this.userID});
final BaseAuth auth;
final VoidCallback onSignedOut;
final String userID;
#override
_UserProfileState createState() => new _UserProfileState();
}
My StatelessWidget Code:
class _UserProfilState extends State<UserProfile> {
final DocumentReference userdocuments =
Firestore.instance.collection("Users").document(widget.userID); //Here i get the Error, because widget.userID
}
My Question: How can i use the the userID Variable from the StatefulWidget, to create a new document based on the userID. Thanks for our help
You can get the value in the initState method
class _UserProfilState extends State<UserProfile> {
DocumentReference userdocuments;
#override
void initState() {
userdocuments =
Firestore.instance.collection("Users").document(widget.userID);
super.initState();
}
}

Resources