How to get data from previous page when using stateful String link.
Is it possible to get string from another file in stateful?
I need to get the string from another file b into the stateful of file a. In case of stateless this was possible, but in stateful it is not possible.
Is there a way to solve this?
I hate to disagree but using global variables in this situation when you can fix your problem easily is not wise although it works and it is very easy.
if you want to send data to another page via pushing a new page you can always use that newPage Constructor
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => BalancePage(
items: "item",
),
),
);
New Page
class BalancePage extends StatefulWidget {
String? items;
BalancePage({
this.items,
});
#override
_BalancePageState createState() => _BalancePageState();
}
if you want to take data from another class you can set a getter
class newVal(){
String val ="ss";
String getVal(){
return val;
}
}
and you can call it anywhere like this
String ss = newVal().getVal;
Related
still new to flutter and I was trying to take multiple values from TextFields in a form to display them in a new screen inside multiple Text elements.
Can someone explain how to do it ?
There are three ways to do it
First method: You can define a class and assign values to it like this:
class Global(){
String text;
}
and then you can import it and assign values or use it like this:
// assign data
Global().text = TextField_controller; // I assume you have already implemented a TextField
// use it
Text(Global().text)
This method is good for passing data between multiple pages but it's not recommended because you can't update the screen when the value changes, it's only good when you need to pass a static variable between multiple pages, for example a user name
Second method: passing data to next page directly
Make the SecondScreen constructor take a parameter for the type of data that you want to send to it. In this particular example, the data is defined to be a String value and is set here with this.text.
class SecondScreen extends StatelessWidget {
final String text;
SecondScreen({Key key, #required this.text}) : super(key: key);
...
Then use the Navigator in the FirstScreen widget to push a route to the SecondScreen widget. You put the data that you want to send as a parameter in its constructor.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => SecondScreen(text: 'Hello',),
));
this method is great for passing data from a parent page to a child page however it can quickly become a nightmare if you want to pass the data to several children down the widget tree or move data back to the parent widget, in that case you can use method 1 or
Third method: using Provider, which is the recommended way, it is similar to the first method but with provider you can ``notify``` all of the listeners to the provider class, meaning you can update the widget whenever the the variable updates, I strongly recommend reading the documentation or watching some YouTube videos, but in short you can use it like this:
after installing the provider package you define your class:
Global extends ChangeNotifierProvider(){
String text;
}
and then add it to the root of your app in main.dart:
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => Global()),
),
],
child: MyApp(),
);
}
and then you define your provider wherever you need to use it
Provider.of<Global>(context, listen: false); // Note that if you want to listen to changes you have to set listen to true
// then you can access your variable like in method 1
insatnce.text = TextField_controller;
// and then you can use it anywhere
Text(instance.text);
again if you find this confusing read the documentation or watch some videos
I'm new in flutter and I read lot of documentations on multiple subjets. One of them is sharing data between screens. I found a lot of solutions and as I'm creating a base project with lot of features, I want to know which one is the best
Solution 1 : In constructor
Basically, when we navigate, we send the data through the next constructor widget.
Solution 2 : In session
Creates a singleton which can be access from everywhere in the application and each time you need to send data, you add it in the session and the next widget can retrieve it.
Solution 3 : In blocs
I read this solution which looks good:
I made a BLoC container class where I've instantiated the BLoCs of the two screen. Then here I set the reference from the BLoC A to a stream of the BLoC B where I want to send the data. The BLoCs are still decoupled cause they don't know anything about each other, the BLoC A doesn't get passed through the constructor on the BLoC B and vice versa, but it just knows that it will receive some data on one of its streams.
UPDATED:
Solution 4 : Inherited widget
With a static function like :
static InheritedDataProvider of(BuildContext context) => context.inheritFromWidgetOfExactType(InheritedDataProvider);
}
So you can access to the data initialized in the parent with something like :
final data = InheritedDataProvider.of(context).data;
Maybe there are others solutions and I'll be glad to know them.
Thanks
The best way is passing a parameter to the constructor
Navigator.push(
context,
PageTransition(
type: PageTransitionType.fade,
child: LoginPage(
userModel: model,
)));
then :
class LoginPage extends StatefulWidget {
LoginPage({this.userModel});
User userModel;
#override
_LoginPageState createState() => _LoginPageState(userModel: userModel);
}
class _LoginPageState extends State with TickerProviderStateMixin {
User userModel;
_LoginPageState({this.userModel});
}
}
What I use:
Call next screen with Navigator.pushNamed(ctx, '/foo', arguments: bar). Only include arguments if needed (e.g. for "update detail" screen).
Centralize all possible routes in the widget that contains MaterialApp.
Pass a clone of the passed argument to the next screen (immutable data).
In code:
...
MaterialApp(
onGenerateRoute: (s) => MaterialPageRoute(builder: (ctx) => _route(s), settings: s),
)
...
Widget _route(RouteSettings route) {
switch (route.name) {
case '/signup':
return SignupRoute();
case '/vendor':
return VendorRoute((route.arguments as Vendor)?.data?.clone());
default:
throw ('No match for ${route.name}');
}
}
Can someone tell me what is happening in this program?
body: new ListView.builder(
itemBuilder: (BuildContext context, int index) {
return new StuffInTiles(listOfTiles[index]);
},
itemCount: listOfTiles.length,
),
),
);
}
}
class StuffInTiles extends StatefulWidget{
final MyTile myTile;
const StuffInTiles(this.myTile);
#override
StuffInTilesState createState() => StuffInTilesState();
}
class StuffInTilesState extends State<StuffInTiles> {
#override
Widget build(BuildContext context) {
return Container(child:
//Text(widget.myTile.title),);
_buildTiles(widget.myTile));
}
Widget _buildTiles(MyTile t) {
I want to understand how passing parameters works,why i have
const StuffInTiles(this.myTile);
in this program, what this code is doing?
in my class StuffInTilesState extends State<StuffInTiles> i don't have any constructor, so how this code is working? why my parameters just happen to be there? before i was learning C++, so this is like a magic to me
If you learned C++ you are probably familiar with initializer list, which Dart has as well. In C++ you could do something:
MyClass {
MyClass(MyTitle title) : this.myTitle = title;
final MyTitle myTitle;
}
Which is also valid in Dart. However, Dart allows you to shorthand the call, by automatically assigning the reference to the new class property, without using any intermediate variable.
MyClass(this.myTitle);
Which is basically the same but ensures that any given property won't be null unless you explicitly pass null.
There are other type of constructors available on Dart, such as private constructors, factory constructors and named constructors. You may want to check the official documentation to learn more about it.
By default, when you create classes in Dart, there is just a default constructor implemented.
For example, if you have a class named AwesomeWidget. It will have a default constructor AwesomeWidget() that lets you create an instance of this widget.
So you could use a default constructor in code like so:
//Example 1
return AwesomeWidget();
//Example 2
AwesomeWidget myWidget = AwesomeWidget();
//Example 3
//...
Row(
children: [
Text("Example Code!"),
AwesomeWidget(),
Text("Example Footer Code!"),
],
),
//...
Now if you want to pass some values or some data to your Widget classes then you use the code you have posted above in your question.
The question is: Why would we want to send data to our widgets?
Answer: The biggest use case is when we make our list items as separate widgets. For example, in my food app, I have to show my user's order history in a ListView, so for the UI of each individual list item, I will just make a reusable Widget called OrderHistoryListItem.
In that OrderHistoryListItem, you want to show the date and time of the object. And the order id, and how much the user paid in that order or any other details, so to display this, we send this data to our Reusable Widget List Item, which displays it. Simple as that.
And that is one of the reasons why we pass values to Widgets. As a programmer, you can make use of this handy feature for more complex scenarios, be creative!
I am running into a problem which I find difficult to describe.
I have a class with two variables. On page 1, I would like to show variable 1. Then, if the user progresses to page 2, I would like to display a widget with variable 1 and 2. I understood how to pass data from one screen to another, but how would I progress if I had to get more data one the second page.
This is the class:
class Dog {
String name;
String age;
Dog({ this.name, this.age });
}
On the first page, I only define the String name, but not the age. Hence, when the user progresses to the second page, I pass the name data as follows (from a list of dogs):
Navigator.push(context,
MaterialPageRoute(
builder: (context) => Screen2(dog: dogs[index]),
),
);
On the second screen, I would like to show a statelesswidget with both class variables, but I only passed one:
final Dog dog;
Screen2({Key key, #required this.dog}) : super(key: key);
In the last code, "this.dog" only includes the name String.
How could I now add the age String as well? Do I have to add it to Navigator.push, or is there a way to add it in the statelesswidget?
Thanks so much in advance for any guidance you can give me!
This is problably sthg simple, I would like to pop a widget and to pass different parameters, here is what I have :
class MyScreen extends StatefulWidget {
final String param0;
final String param1;
final String param2;
MyScreen(param0,param1,param2);
#override
MyState createState() => new MyScreenState();
}
...
I would like to go back to this widget passing parameters, something like this :
Navigator.pop(context, "NewParam0", "NewParam1", "NewParam2");
but it doesn't work.
I can pop with 1 parameter and the context, but it doesn't work with multiple parameters,
Any idea?
Yep, the solution is simple! The way I've dealt with this is by popping an object. For instance, a Map<String, String>:
Navigator.pop(context,
{"NewParam0": "param0value", "NewParam1": "param1value", "NewParam2": "param2value"}
);
(see https://api.flutter.dev/flutter/widgets/Navigator/pop.html and https://flutter.dev/docs/cookbook/navigation/returning-data)
You could also make a lightweight class to pop that will populate default params, etc. if you have a lot of complexity to pass back and forth, though at that point, I might try to rework my state management a little bit.