Passing a StatefulWidget as argument and accessing its Constructor - flutter

I have created a custom StatefulWidget that takes a Widget as an argument.
import 'package:flutter/material.dart';
class CustomWidget extends StatefulWidget {
final Widget myWidget;
CustomWidget({this.myWidget});
#override
_CustomWidgetState createState() => _CustomWidgetState();
}
class _CustomWidgetState extends State<CustomWidget> {
#override
Widget build(BuildContext context) {
return Container(
child: widget.myWidget(name: 'ASAD'), //I want to achieve this
);
}
}
I'm passing another StatefulWidget named Profile as that argument widget. Now I want to access that passed widget's constructor.
import 'package:flutter/material.dart';
class Profile extends StatefulWidget {
final String name;
Profile({this.name});
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
#override
Widget build(BuildContext context) {
return Center(child: Text('${widget.name}'),);
}
}
I'm using the CustomWidget which takes a widget as argument here
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomWidget(myWidget: Profile(),) //I don't want to pass the argument here
);
}
}
I was able to accomplish something like this using typedef but it started throwing an error.
typedef CustomCallBack = Widget Function({String name});
class CustomWidget extends StatefulWidget {
final CustomCallBack myWidget;
CustomWidget({this.myWidget});
#override
_CustomWidgetState createState() => _CustomWidgetState();
}
class _CustomWidgetState extends State<CustomWidget> {
#override
Widget build(BuildContext context) {
return Container(
child: widget.widget(name: 'ASAD'), //I'm able to access the constructor here but now I get an error.
);
}
}
Error
error: The argument type 'Profile' can't be assigned to the parameter type 'Widget Function({String name})'. (argument_type_not_assignable
Note: Based on the app that I'm working on but cannot share code, I have recreated this scenario and is same as far as the issue is concerned.

Try the change this line in the CustomWidget widget,child: widget.widget(name: 'ASAD'), for the widget that you are passing only, without putting the (name: 'ASAD').
So when you pass the Profile Widget, that's when you must specify the value of the name parameter!
body: CustomWidget(myWidget: Profile(name: 'ASAD'),)

please try to use this :
import 'package:flutter/material.dart';
typedef CustomCallBack = Widget Function(String name);
class CustomWidget extends StatefulWidget {
final CustomCallBack myWidget;
CustomWidget({this.myWidget});
#override
_CustomWidgetState createState() => _CustomWidgetState();
}
class _CustomWidgetState extends State<CustomWidget> {
#override
Widget build(BuildContext context) {
return Container(
child: widget.myWidget(
'ASAD'), //I'm able to access the constructor here but now I get an error.
);
}
}
class Profile extends StatefulWidget {
final String name;
Profile({this.name});
#override
_ProfileState createState() => _ProfileState();
}
class _ProfileState extends State<Profile> {
#override
Widget build(BuildContext context) {
return Center(
child: Text('${widget.name}'),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomWidget(
myWidget: (name) => Profile(
name: name,
),
) //I don't want to pass the argument here
);
}
}

Related

How to use a method in a Stateful Widget from another Widget

So i have this toggle() method in the Stateful SideBar class
class SideBar extends StatefulWidget {
const SideBar({super.key});
#override
State<SideBar> createState() => _SideBarState();
}
class _SideBarState extends State<SideBar> with SingleTickerProviderStateMixin{
void toggle() {
if (_controller.isCompleted) {
_controller.reverse();
}
else {_controller.forward();}
}
}
and i want to use it in
class SideBarWidget extends StatelessWidget {
SideBarWidget({Key? key}) : super(key: key);
final SideBar sideBarWidget = SideBar(...);
void toggle() {
// here i want to use the toggle() method
}
#override
Widget build(BuildContext context) {
return sideBarWidget;
}
}
I cannot use sideBarWidget.toggle()
I also cannot pass it as a parameter becasue the _controller is in the SideBar() widget
There are many ways, but the most common and simple is to create an instance of the SideBar class inside the SideBarWidget class, for example:
var side = SideBar();
And then you can access the toggle() method like this: side.toggle().
remove underscore from SideBarState
to use method of SideBarState in SideBarWidget use: SideBarState().toggle();
**screen1.dart**
class ParentWidget extends StatefulWidget {
const ParentWidget({Key? key}) : super(key: key);
#override
State<ParentWidget> createState() => ParentWidgetState();
}
class ParentWidgetState extends State<ParentWidget> {
void printData() {
print("parent");
}
#override
Widget build(BuildContext context) {
return const Placeholder();
}
}
**screen2.dart**
import 'package:demo/screen_1.dart';
import 'package:flutter/material.dart';
class ChildWidget extends StatelessWidget {
const ChildWidget({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
ParentWidgetState().printData();
return const Placeholder();
}
}
One way is to give the SideBar a GlobalKey and get the state from the key afterwards. An example:
class SideBar extends StatefulWidget {
const SideBar({super.key});
#override
State<SideBar> createState() => SideBarState();
}
class SideBarState extends State<SideBar> with SingleTickerProviderStateMixin{
#override
Widget build(BuildContext context) {
return Container();
}
void toggle() {
print('toggle');
}
}
class SideBarWidget extends StatelessWidget {
SideBarWidget({Key? key}) : super(key: key);
final GlobalKey<SideBarState> sideBarKey = GlobalKey();
late final SideBar sideBarWidget = SideBar(key: sideBarKey);
void toggle() {
sideBarKey.currentState?.toggle();
}
#override
Widget build(BuildContext context) {
return Column(
children: [
TextButton(onPressed: toggle, child: const Text('click')),
sideBarWidget,
],
);
}
}

create two pages in flutter project

I am a flutter beginner, I want to create a flutter application that contains two pages, I encounter an error that I do not understand.
Here is my code:
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
MyApp({super.key});
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: FirstPage(),
);
}
}
class FirstPage extends StatefulWidget {
FirstPage({super.key});
#override
State<MyApp> createState() => _FirstPageState();
}
class _FirstPageState extends State<MyApp> {
String bottonName = 'click';
int currentIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
....
);}}
L'erreur est la suivante:
StatefulWidget.createState must return a subtype of State<FirstPage>
The createState function for FirstPage returned a state of type _FirstPageState, which is not a subtype of State<FirstPage>, violating the contract of createState.
the state type of your First screen is from another widget. change it with this:
class FirstPage extends StatefulWidget {
FirstPage({super.key});
#override
State<FirstPage> createState() => _FirstPageState();
}
class _FirstPageState extends State<FirstPage> {
String bottonName = 'click';
int currentIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
....
);}} ```

Call setState method in Constructor Error

I want to call method from another class which contains setState. I got some error in page 2like this
This happens when you call setState() on a State object for a widget that hasn't been inserted into the widget tree yet. It is not necessary to call setState() in the constructor, since the state is already assumed to be dirty when it is initially created.
I've read this answer, but I didnt get it on my case. Any Ideas? Thank you
class Page1 extends StatefulWidget {
#override
_Page1State createState() => _Page1State();
}
class _Page1State extends State<Page1> {
#override
void initState(){
Page2().method();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
),
);
}
}
class Page2 extends StatefulWidget {
method() => createState().methodInPage2();
#override
_Page2State createState() => _Page2State();
}
class _Page2State extends State<Page2> {
Future<List<String>> methodInPage2() async{
//error here
setState(){
//setState here,
}
}
#override
Widget build(BuildContext context) => Container();
}

Accessing Classes in different pages

can somebody explain me when we have one file like Home.dart i have access to extends state classes and it's static variables
Home.dart
import 'package:flutter/material.dart';
class FirstClass extends StatefulWidget {
const FirstClass({Key? key}) : super(key: key);
#override
State<FirstClass> createState() => _FirstClassState();
}
class _FirstClassState extends State<FirstClass> {
static void someFunc() {
print('nothing');
}
#override
Widget build(BuildContext context) {
return Container();
}
}
class SecondClass extends StatefulWidget {
const SecondClass({Key? key}) : super(key: key);
#override
State<SecondClass> createState() => _SecondClassState();
}
class _SecondClassState extends State<SecondClass> {
#override
Widget build(BuildContext context) {
return ElevatedButton(onPressed: _FirstClassState.someFunc, child: Text(' '));
}
}
but when we have two different file like home1.dart and home2.dart we cant access to extends state classes?
Home1.dart
import 'package:flutter/material.dart';
class FirstClass extends StatefulWidget {
const FirstClass({Key? key}) : super(key: key);
#override
State<FirstClass> createState() => _FirstClassState();
}
class _FirstClassState extends State<FirstClass> {
static void someFunc() {
print('nothing');
}
#override
Widget build(BuildContext context) {
return Container();
}
}
Home2.dart
import 'package:flutter/material.dart';
import 'Home1.dart';
class SecondClass extends StatefulWidget {
const SecondClass({Key? key}) : super(key: key);
#override
State<SecondClass> createState() => _SecondClassState();
}
class _SecondClassState extends State<SecondClass> {
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: **_FirstClassState.someFunc?????**, child: Text(' '));
}
}
i know i can have access to FirstClass but why can not have access to _FirstClassState ?
I think it is better to separate your widget classes and logic classes that contains some function.
Since you are extending Stateless/Stateful widget, the class is becoming a widget.
Create you method or function in another class and don't extend anything if you don't have to then use static keyword in front of the functions so that you can access those functions inside another class or let's say in your stateful widget class.
However, if you need to pass values from one Stateful widget to another then add that object to your widget's constructor. Example as follows:
class FirstClass extends StatefulWidget {
String username = ""; //Creating & initializing username variable
//Adding username variable inside constructor
const FirstClass({Key? key, required this.username}) : super(key: key);
#override
State<FirstClass> createState() => _FirstClassState();
}
class _FirstClassState extends State<FirstClass> {
static void someFunc() {
print('nothing');
}
#override
Widget build(BuildContext context) {
return Text(widget.username); //Accessing username
}
}
Then, pass your value in the widget like this:
class SecondClass extends StatefulWidget {
const SecondClass({Key? key}) : super(key: key);
#override
State<SecondClass> createState() => _SecondClassState();
}
class _SecondClassState extends State<SecondClass> {
#override
Widget build(BuildContext context) {
return FirstClass(username: "Tricolore"); //Passing username value
}
}

how to pass a variable as a parameter to a widget two, modify it there, and return the modified value to widget one, Flutter

how to pass a variable as a parameter to a widget two, modify it there, and return the modified value to widget one.
I need to change the value of the variable when I click the "Change it" button, and that change is reflected in widget one.
class FirstWidget extends StatefulWidget {
#override
_FirstWidgetState createState() => _FirstWidgetState();
}
class FirstWidgetState extends State<FirstWidget> {
String c = 'start';
#override
Widget build(BuildContext context){
return Container(
child: SecondWidget(variable: c),
);
}
}
class SecondWidget extends StatefulWidget {
String variable;
SecondWidget({ this.variable });
#override
_SecondWidgetState createState() => _SecondWidgetState();
}
class SecondWidgetState extends State<SecondWidget> {
#override
Widget build(BuildContext context){
return Container(
child: RaisedButton(child:Text('Change it'), onPressed: () {widget.variable = 'end';}),
);
}
}
It is possible to implement it easily with a callback, meaning you pass a function to your second widget, and when the button is clicked you call the function, this way you can modify whatever you want in the first widget.
Like this:
class FirstWidget extends StatefulWidget {
#override
_FirstWidgetState createState() => _FirstWidgetState();
}
class FirstWidgetState extends State<FirstWidget> {
String c = 'start';
#override
Widget build(BuildContext context){
return Container(
child: SecondWidget(variable: c, onChange: (newVal) {
setState(() {c = newVal;});
}),
);
}
}
class SecondWidget extends StatefulWidget {
String variable;
final onChange;
SecondWidget({ this.variable, this.onChange });
#override
_SecondWidgetState createState() => _SecondWidgetState();
}
class SecondWidgetState extends State<SecondWidget> {
#override
Widget build(BuildContext context){
return Container(
child: RaisedButton(child:Text('Change it'), onPressed: () {widget.onChange('end');}),
);
}
}