error: The return type 'CategoryState' isn't a 'Widget', as required by the closure's context - flutter

I tried to put the route to Another Class on the Same Page and wrote this code as mentioned in the flutter Doc, but I get this:
error: The return type CategoryState isn't a Widget, as required
by the closure's context.
Page code:
Navigation code:

According to the documentation: the builder function of the MaterialPageRoute class should return a widget. Both StatelessWidget and StatefulWidget extend the Widget class and thus can be used here.
But in your case the CategoryState class does not extend any of them, and it's the reason you are having that error.
You need to use the Category class instead.
It should then look like:
PAGE :
class Category extends StatefulWidget {
#override
_CategoryState createState() => _CategoryState();
}
class _CategoryState extends State<Category> {
#override
Widget build(BuildContext context) {
return Column(
children: [
Container(child: Text("Music")),
Container(child: Text("Projects")),
Container(child: Text("Essay")),
],
);
}
}
NAVIGATION
Navigator.push(
context,
MaterialPageRoute(builder: (context) => Category())
);
Furthermore, I would advise you to add a suffix to this class name (e.g. CategoryScreen) in order to avoid name conflicts in case you have another class (e.g. a model) with the same name.

class CategoryState is not a widget it's just a Dart class you want to navigate to Category()

Related

How to acces parameter value from constructor in flutter?

I'm having trouble with accessing the value of a parameter from a constructor in my code. I access to this page from another one where I get the value of the parameter:
final route = MaterialPageRoute(
builder: (context) => AnadirJugadores(idPagina: respuesta['id'],));
Navigator.push(context, route);
This is the code of AnadirJugadores:
class AnadirJugadores extends StatefulWidget {
final String idPagina;
AnadirJugadores({required this.idPagina });
String cogerID() {
return this.idPagina;
}
#override
State<AnadirJugadores> createState() => _AnadirJugadoresState();
}
class _AnadirJugadoresState extends State<AnadirJugadores> {
#override
Widget build(BuildContext context) {
.... more code
ElevatedButton(
child: Text(idPartida), // this is the line of the error
onPressed: () {
final data = ClipboardData(text: '25342756374');
Clipboard.setData(data);
},
),
I'm trying to access the value of idPagina. How could I do that?
Thanks in advance.
When using stateful widgets you need to use widget to access the parameters.
child: Text(widget.idPartida),
In StatefulWidget your constructor exists in upper class (it's not in State class), so to access data in this constructor in your state class you should do this:
ElevatedButton(child: Text(widget.idPartida), ...),

what does it mean when we see people calling widget in dart?

I have seen many times people calling widget. sth inside the code.
May I know what it is actually doing?
For example code below, (highlighted part is my confusion)
class _MyOwnClassState extends State<MyOwnClass> {
#override
Widget build(BuildContext context) {
return ListTile(
title: Container(
child: Column(children: makeWidgetChildren(**widget.jsonObject)**),
),
);
}
}
In flutter's StatefulWidget, we have the following architecture.
You have a StatefulWidget like this,
class MyOwnClass extends StatefulWidget {
State createState () => _MyOwnClassState();
}
And you have a State class for your StatefulWidget like this,
class _MyOwnClassState extends State<MyOwnClass> {
}
Now, State class is meant to house variables that tend to change in order for your UI to be rebuilt.
So you can have variables in your State that you can update using setState.
But what if you had some data that doesn't change and you want to avoid putting them inside the State class.
That's where your StatefulWidget comes to play.
You can store variables in your MyOwnClass and the widget variable inside the State class gives you a way to access them.
For example,
class MyOwnClass extends StatefulWidget {
int numberThatDoesntChange = 1;
State createState () => _MyOwnClassState();
}
You can access them in your State class like this,
class _MyOwnClassState extends State<MyOwnClass> {
Widget build(BuildContext context) {
return Text('$widget.numberThatDoesntChange');
}
}
Apart from this, your StatefulWidget has many more internal instance members that you can access inside of your State class using the widget variable.
The widget refers to the actual view that renders on the screen. It extends the StatefulWidget class of the flutter framework and overrides the createState() method. The createState() method is used to create the instance of state class. We will look into createState().
The state class is used to maintain the state of the widget so that it can be rebuilt again. It extends the State class of the flutter framework and overrides the build method.
The framework calls build() method again and again whenever setState() method is called. The setState() method notifies the framework that the internal state of this object has changed and it should be rebuilt. Suppose we change the value of text in StatefulWidget then we need to call setState().
Edit As Nisanth pointed outh in his comment - I missed your question completely; please ignore the below....
Let me try my answer, I don't think others are getting your point.
In your exapmle, Column(children: x) expect a list of Widgets.
You have two options - either provide this list directly:
class _MyOwnClassState extends State<MyOwnClass> {
#override
Widget build(BuildContext context) {
return ListTile(
title: Container(
child: Column(children: <Widget>[SomeWidget()]),
),
);
}
}
Or if you have more complex code that generates widget - based on input parameters, or you have the same widget generated multiple times and you want to avoid the code duplication - you would create the separate function to do the job.
Something like:
class _MyOwnClassState extends State<MyOwnClass> {
List<Widget> makeWidgetChildren(int param) {
/*
some very complex logic here
/*
if (param>3 && param<4) {
return List<Widget>.generate(4, (index)=>SomeWidget1(index));
} else {
return <Widget>[Center()];
}
}
#override
Widget build(BuildContext context) {
return ListTile(
title: Container(
child: Column(children: makeWidgetChildren(**widget.jsonObject)**),
),
);
}
}
So basically, it is just to make the code nicer; and to avoid having code repeated over and over again in the build function.

How to use Provider/Consumer when extending a class

To start, I'm new to Flutter, so I am completely open to the possibility that my problem stems from a fundamental misunderstanding, but here is my question:
I am trying to get a good understanding of how to use Provider in conjunction with with the get_it package.
I think I understand how to use the Provider pattern in the standard case, by which I mean creating a unique class with a view and a view_model. Where I seem to have become lost is when I design a custom widget as a base template class and then extend that widget so that it can be tailored for use in a specific class view, I'm not seeing how to connect it to the Provider pattern because the base class doesn't know in advance which view_model it needs to listen to.
Below I will provide short example of what I am doing in the standard case, where things seem to work fine, and then I will show a short example of how I am trying to build the custom widget and extend it...
Here is the sample standard way in which I am using the Provider pattern with get_it, in which everything seems to work just fine:
class MyScreenView extends StatefulWidget{
#override
_ProfileEditScreenViewState createState() => _ProfileEditScreenViewState();
}
class _MyScreenViewState extends State<MyScreenView>{
final MyScreenViewModel model = serviceLocator<MyScreenViewModel>();
#override
Widget build(BuildContext context) {
return ChangeNotifierProvider<MyScreenViewModel>(
create: (context) => model,
child: Material(
color: Colors.white,
child: Consumer<MyScreenViewModel>(
builder: (context,model,child) => Text(model.someText),
),
),
);
}
}
class MyScreenViewModel extends ChangeNotifier{
String? _someText;
MyScreenViewModel() {
this._someText= 'Sample Text';
}
String get someText=> _someText;
set someText(String value) {
_someText= value;
notifyListeners();
}
}
Here is an example of how I am trying to build a base class, but am uncertain as to how I go about connecting it to Provider: (The idea here is that the below widget would be part of a more complex widget that would have a view_model where the state for the overall widget would be maintained)
class BaseCheckBoxTile extends StatefulWidget{
bool isChecked;
Function(bool) checkBoxOnChanged;
BaseCheckBoxTile({this.isChecked = false, required this.checkBoxOnChanged});
#override
_BaseCheckBoxTileState createState() => _BaseCheckBoxTileState();
}
class _BaseCheckBoxTileState extends State<BaseCheckBoxTile>{
#override
Widget build(BuildContext context) {
return SizedBox(
child: Checkbox(value: widget.isChecked,onChanged: widget.checkBoxOnChanged,),
);
}
}
class CustomCheckBoxTile extends BaseCheckBoxTile{
bool isChecked;
Function(bool) checkBoxOnChanged;
CustomCheckBoxTile({this.isChecked =false, required this.checkBoxOnChanged})
:super(isChecked: isChecked, checkBoxOnChanged: checkBoxOnChanged);
}
My instinct is to want to put something in my _BaseCheckBoxTileState that gives me access to the larger widget's view_model, like what I do in the first example with:
"MyScreenViewModel model = serviceLocator<MyScreenViewModel>(); "
If I had that, then I could assign the values in my _BaseCheckBoxTileState by referring to the model instead of widget (e.g., model.isChecked instead of widget.isChecked). The model would obviously extend ChangeNotifier, and the view that is making use of the custom widget would wrap the widget in a Consumer. However, the _BaseCheckBoxTileState doesn't know what view_model to listen to.
Would I accomplish this by putting some generic Type or Object in for my View_Model which could be assigned when the class is built? Or am I approaching this in a completely wrong way?

How do i access a varible from another class in Flutter

I'm making my first flutter app.
it asks for some information then when you click a button it shows the information you entered on another page, I wanted to ask. How do I get a variable from another class?
so I can use the information entered on another page
It seems like you want to pass some data while navigating to another page. If I'm not wrong You should define a variable in the destination like this:
class NewPage extends StatefulWidget {
final int someInt;
NewPage({Key key, this.someInt}) : super(key: key);
#override
_NewPageState createState() => _NewPageState();
}
class _NewPageState extends State<NewPage> {
#override
Widget build(BuildContext context) {
return Container(
child: Container(child: Text("${widget.someInt}"),),
);
}
}
In the above code I passed someInt to NewPage class.
In the first page you should navigate like this:
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NewPage(someInt: 293,),
));
put above code in the onPressed and pass the data with constructor.

How do I navigate to a page that has a constructor parameter?

I have a flutter stateful page. Here it is:
class TestPage extends StatefulWidget {
static const String id = 'TestPage';
final String testString;
TestPage(this.testString);
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(child: Text('Hello ${widget.testString}'))
);
}
}
The page has a constructor that takes in a string as a default value.
final String testString;
From another page, I make a call to that page. I want to open it and give it or pass to it a String value:
Navigator.pushNamed(context, TestPage(myString));
However, it is telling me:
that the argument type 'TestPage' cannot be assigned to the parameter type String.
What am I doing wrong? Is this not the correct way to instantiate this class and make it appear?
Thank you
Try with this,
Navigator.push( context, MaterialPageRoute( builder: (context) => TestPage(testString: 'Hello',), ));