How to call a function in a StatefulWidget from another StatefulWidget? - flutter

I am trying to call a function(addGeoPoint) from Map class in another function named onDragEnd of the class SwipeButton both of which is are stateful.
class Map extends StatefulWidget {
//Some Code
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
//Some Functions
void addGeoPoint() async{
}
File 2
class SwipeButton extends StatefulWidget {
// Some Code
#override
SwipeButtonState createState() => SwipeButtonState();
}
class SwipeButtonState extends State<SwipeButton>
with SingleTickerProviderStateMixin {
// Some functions
void _onDragEnd(DragEndDetails details) {
// I want to call the addGeoPoint() function here
}
}
To do so, I tried creating an instance of the class Map as Map mapScreen = new Map and then access the function using mapScreen.addGeoPoint() but, I achieved no success. Any help to solve this problem would be appreciated.

You can use VoidCallBacks to communicate between Widgets:
Map:
class Map extends StatefulWidget {
//Some Code
_MapState createState() => _MapState();
}
class _MapState extends State<Map> {
//Some Functions
void addGeoPoint() async{
//do things
}
Widget buildSwipeButton() {
...
...
return SwipeButton(
onAddGeoPoint: addGeoPoint,
);
}
SwipeButton:
class SwipeButton extends StatefulWidget {
final VoidCallback onAddGeopoint;
SwipeButton({this.onAddGeoPoint});
// Some Code
#override
SwipeButtonState createState() => SwipeButtonState();
}
class SwipeButtonState extends State<SwipeButton>
with SingleTickerProviderStateMixin {
// Some functions
void _onDragEnd(DragEndDetails details) {
// I want to call the addGeoPoint() function here
widget.onAddGeoPoint();
}
}

You can declare your widget like this
class YourWidget extends StatefulWidget {
final Function callback;
YourWidget({#required this.textButton});
#override
YourWidgetState createState() => YourWidgetState();
}
then you can pass de function like this in your stateful parent
YourWidget(
callback: (){}
)
ant then you can use in YourWidget like this in other widget or other function
widget.callback()

Related

How to override State class so I could access StatefulWidget instance?

So I have 2 classes:
class A extends StatefulWidget {
A({Key? key}) : super(key: key);
#override
State<A> createState() => _AState();
}
class _AState extends State<A> {
#override
Widget build(BuildContext context) {
return Container();
}
void func(){}
}
And I want to override the _AState classes func() method. So I do this like this:
class B extends A{
final item = 10;
#override
State<A> createState() => _BState();
}
class _BState extends _AState{
#override
void func() {
widget.item //can't do this
}
}
I have no problem overriding the func() method, but now I also need to access my new variable item, that is declared in B class. And I know I can't do that because instance widget is provided by State<A> class.
So my question is: How to access the variable item from B class in _BState?
Cast the widget to B object
class _BState extends _AState{
#override
void func() {
// (widget as B).item
}
}

how to call function parent to child which is inside model class?

I have this model class which has a refresh method,
class Model{
...
void refresh(){}
}
I'm calling this method from Parent widget like this,
class Parent extends StatefulWidget {
#override
_Parent State createState() => _Parent State();
}
class _Parent State extends State<Parent >
with SingleTickerProviderStateMixin {
final Model model = Model();
#override
Widget build(BuildContext context) {
return Column(
children:[
Child(model: model),
IconButton(onPressed:model.refresh)
]
);
}
}
this is child widget,
class Child extends StatefulWidget {
final Model model;
const Child({
Key? key,
required this.model,
}) : super(key: key);
#override
_ChildState createState() => _ChildState();
}
class _ChildState extends State<Child>
with SingleTickerProviderStateMixin {}
so what I want is to override that method in here and call that whenever it's called from parent.
In short what I need is a callback from parent to child which need to be inside the Model class. So How can I do this?
ok so I knew I can do it with state management but using another library was not a option and I totally forgot about the change notifier so I implemented like this,
class Model extends ChangeNotifier{
void refresh(){
notifyListeners();
}
}
class Child extends StatefulWidget{
final Model model
Child(this.model);
...
#override
initState(){
model.addListener((){});
}
}
class Parent extends StatelessWidget{
final Model model = Model();
...
Child(model),
SomeWidget(
onTap:(){
model.refresh();
}
),
}

The instance member 'widget' can't be accessed in an initializer

In my project, I pass data from one widget to another using this code:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
TranslatorSignUpStep2(transModel: this._translatorModel),
),
);
Then I retrive it in the other widget by the code below:
class TranslatorSignUpStep2 extends StatefulWidget {
final TranslatorModel transModel;
TranslatorSignUpStep2({this.transModel});
#override
_TranslatorSignUpStep2State createState() => _TranslatorSignUpStep2State();
}
The problem is, in the TranslatorSignUpStep2 class I want to assign the passed-in transModel to another variable so I write this code
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
TranslatorModel _translatorModel = widget.transModel;
}
But it seems like the widget can't be used outside the build method so I get error saying
The instance member 'widget' can't be accessed in an initializer.. Anyone know how to get over this ?
you can access widget in initState function like this.
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
TranslatorModel _translatorModel ;
#override
void initState() {
_translatorModel = widget.transModel;
}
}
Just add the keyword late while initializing:
class TranslatorSignUpStep2 extends StatefulWidget {
final TranslatorModel transModel;
TranslatorSignUpStep2({this.transModel});
#override
_TranslatorSignUpStep2State createState() => _TranslatorSignUpStep2State();
}
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
late TranslatorModel _translatorModel = widget.transModel;
}
try this code :
TranslatorSignUpStep2 :
class TranslatorSignUpStep2 extends StatefulWidget {
final TranslatorModel transModel;
TranslatorSignUpStep2({this.transModel});
#override
_TranslatorSignUpStep2State createState() => _TranslatorSignUpStep2State(this.transModel);
}
TranslatorSignUpStep2 class :
class _TranslatorSignUpStep2State extends State<TranslatorSignUpStep2> {
_TranslatorSignUpStep2State(TranslatorModel _tempModel ){
this._translatorModel =_tempModel;
};
TranslatorModel _translatorModel ;
}
Add static keyword when innitializing
class OrderDetails extends StatefulWidget {
int selectedDays;
OrderDetails({
this.range,)};
#override
_OrderDetailsState createState() => _OrderDetailsState();
}
class _OrderDetailsState extends State<OrderDetails> {
String getRange;
#override
void initState() {
super.initState();
getRange = widget.range;
}

How to access passed value in the Statefulwidget?

I am passing an String from another StatefulWidget to the below CardItem StatefulWidget and then from here the String is passed to the _CardItemState as shown in the code below.
But how this String passed should be accessed from _CardItemState(String itemTitle);
class CardItem extends StatefulWidget {
String itemTitle;
CardItem({#required this.itemTitle});
#override
_CardItemState createState() => _CardItemState(itemTitle);
}
class _CardItemState extends State<CardItem> {
_CardItemState(String itemTitle);
void initState(){
print("INiatialize");
print("itemTitle is " + );
}
}
You can access it via widget.itemTitle. For your case you can call it like this:
printItem(){
print("itemTitle is ${widget.itemTitle}");
}
void initState(){
printItem();
super.initState();
}
You also don't need to pass the string in your state constructor. Remove this:
_CardItemState(String itemTitle);
easy! grab it using
widget.itemTitle
class CardItem extends StatefulWidget {
String itemTitle;
CardItem({#required this.itemTitle});
#override
_CardItemState createState() => _CardItemState(itemTitle);
}
class _CardItemState extends State<CardItem> {
String itemTitle; // - 1
_CardItemState(this.itemTitle); // - 2
void initState(){
itemTitle = widget.itemTitle; // - 3;
print("INiatialize");
print("itemTitle is " + itemTitle ); // - 4
print("itemTitle is " + widget.itemTitle ); // same as - 4
}
}
Best way to do this is to use
widget.fieldName
class CardItem extends StatefulWidget {
String itemTitle;
CardItem({#required this.itemTitle});
#override
_CardItemState createState() => _CardItemState(itemTitle:itemTitle);
}
class _CardItemState extends State<CardItem> {
String myItemTitle;
#override
void initState(){
super.initState();
myItemTitle=widget.itemTitle;
print("INiatialize");
print("itemTitle is $myItemTitle";
}
}
otherway round to this problem is to pass data in constructor as shown below, but the above method is recommended to be followed.
class CardItem extends StatefulWidget {
String itemTitle;
CardItem({#required this.itemTitle});
#override
_CardItemState createState() => _CardItemState(itemTitle:itemTitle);
}
class _CardItemState extends State<CardItem> {
String itemTitle;
_CardItemState({this.itemTitle});
void initState(){
print("INiatialize");
print("itemTitle is $itemTitle";
}
}

flutter access store mobx from other screen

how to accessing the MobX stores across the screen like inject store in react?
class LoginScreen extends StatefulWidget {
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
final _store = exStore();
void init() {
_store.setTitle('foo');
}
}
when navigate to home screen, i need to get data title
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final _store = exStore();
void init() {
print(_store.title); // return null
}
}
i need the _store.title return 'foo'..
It's simple, you just need to create your instance outside of any widget so that be global, like following..
screen A
store = exStore();
class LoginScreen extends StatefulWidget {
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
void init() {
store.setTitle('foo');
}
}
screen B
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
void init() {
print(store.title); // return null
}
}