How do you pass properties to a widget class in flutter.
Here is a basic class
class ToolbarToggle extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Text(label);
}}
I want to be able to call it
ToolbarToggle(label: 'a label')
Forgive the elementary question.
First you declare a label property, like this:
class ToolbarToggle extends StatelessWidget {
final String label;
#override
Widget build(BuildContext context) {
return Text(label);
}
}
final means the value is immutable, you should add it to every property on a StatelessWidget.
Now we need to declare a Constructor, here is how we do that:
ToolbarToggle(this.label);
This means that when creating a ToolbarToggle, we can do this: ToolbarToggle('some label');. In order to make parameters named, we need to declare the constructor like so:
ToolbarToggle({this.label});
Now it is possible to call ToolbarToggle(label: 'my label');. But this will give an error, because it's possible you don't actually pass any value when calling the constructor. To fix this, you should either make it a required parameter, or give it a default value:
ToolbarToggle({required this.label});
ToolbarToggle({this.label=''});
Here is the final class code:
class ToolbarToggle extends StatelessWidget {
ToolbarToggle({required this.label});
final String label;
#override
Widget build(BuildContext context) {
return Text(label);
}
}
class ToolbarToggle extends StatelessWidget {
final String? label;
const ToolbarToggle({this.label, Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text(label ?? 'label is null');
}}
Like this, you can pass properties,
Its recommended to use const constructor and a key param ( to uniquely identify incase)
You missed using the label
class ToolbarToggle extends StatelessWidget {
final String label;
ToolbarToggle({required this.label});
#override
Widget build(BuildContext context) {
return Text(label);
}}
Related
I am trying to create a couple of widgets A that all should belong to another type of widget B, so that in the end all of them could be passed to a constructor that accepts only widgets of type B, but not other custom widgets like Container, Text, etc.
I tried something like this:
Parent class:
class ProDynamicWidget {
const ProDynamicWidget({
required this.height
});
final double height;
}
Child classes:
class ProDynamicTitle extends ProDynamicWidget {
final String title;
ProDynamicTitle({
required this.title
}) : super(height: 50.0);
// Here should be a build method for the title
}
############################################################
class ProDynamicImage extends ProDynamicWidget {
final String imageUrl;
ProDynamicImage({
required this.imageUrl
}) : super(height: 70.0);
// Here should be a build method for the image
}
I then wanted to create a widget that only accept widgets of type ProDynamicWidget:
class TestOneWidget extends StatelessWidget {
const TestOneWidget({
Key? key,
required this.widget
}) : super(key: key);
final ProDynamicWidget widget;
#override
Widget build(BuildContext context) {
return Container();
}
}
I do not really get how can now end up with child widgets that have separate build methods and a way the constructur at the end only accepts these child widgets instead of every type of widget.
Make ProDynamicWidget abstract and let it extend StatelessWidget:
abstract class ProDynamicWidget extends StatelessWidget{
const ProDynamicWidget({
required this.height
});
final double height;
}
Next, ProDynamicTitle and ProDynamicImage simply extend ProDynamicWidget and will thus have to define the build method:
class ProDynamicTitle extends ProDynamicWidget {
final String title;
const ProDynamicTitle({
required this.title
}) : super(height: 50.0);
#override
Widget build(BuildContext context) {
return Text(title);
}
}
class ProDynamicImage extends ProDynamicWidget {
final String imageUrl;
const ProDynamicImage({
required this.imageUrl
}) : super(height: 70.0);
#override
Widget build(BuildContext context) {
return Image(image: NetworkImage(imageUrl));
}
}
You can keep TestOneWidget as is. It will only accept descendants of ProDynamicWidget.
I just need to pass an attribute to a constructor AppTheme, but i received an error:
All final variables must be initialized, but '' isn't.
Try adding an initializer for the field.dartfinal_not_initialized_constructor
the code is:
class AppTheme extends StatelessWidget {
const AppTheme({required this.navigator}); // => Cursor error
final Widget navigator,
#override
Widget build(BuildContext context) {
throw UnimplementedError();
}}
class AppTheme extends StatelessWidget {
const AppTheme({required this.navigator});
final Widget navigator; // from , to ;
#override
Widget build(BuildContext context) {
throw UnimplementedError();
}}
There quote is from Riverpod documentation:
A StatefulWidget that can use Hook
It's usage is very similar to StatefulWidget, but use hooks inside
State.build.
The difference is that it can use Hook, which allows HookWidget to
store mutable data without implementing a State.
besides this, I can't find any sample code or another tutorial or any description more than the quote.
in this simple HookWidget how can I implement that with StatefulHookWidget?
class MyHomePage extends HookWidget {
#override
Widget build(BuildContext context) {
final store = useMemoized(() => MyStore());
return Container();
}
}
A StatefulHookWidget is for when you need to use any of the overridable functions of a regular StatefulWidget - like didChangeDependencies, or initState, or dispose.
Generally, unless you have a really good or niche reason to use StatefulHookWidget, do prefer HookWidget.
Essentially, if we replicate your example, both Class1 and Class2 are equivalent in terms of the end product. The only difference is the verbiage needed to get there.
class Class1 extends HookWidget {
const Class1({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final store = useMemoized(() => MyStore());
return Container();
}
}
class Class2 extends StatefulHookWidget {
const Class2({Key? key}) : super(key: key);
#override
_Class2State createState() => _Class2State();
}
class _Class2State extends State<Class2> {
#override
Widget build(BuildContext context) {
final store = useMemoized(() => MyStore());
return Container();
}
}
I am on the latest version of riverpod so I am using StatefulHookConsumerWidget
Following is one way to implement StatefulHookConsumerWidget. This might give you a hint for your answer
class MyHomePage extends StatefulHookConsumerWidget {
#override
_MyHomePage State createState() => _SocietyHomeState();
}
class MyHomePage extends ConsumerState<SocietyHome> {
Widget build(BuildContext context) {
return Container();
}
}
I am quite puzzled about the values being passed in the class constructor not being available in the Widget.
I am passing the value of the cards in the widget constructor, but when debugging it and after they are build the Text widgets do not have any text.
Initializing the Widget with the values.
Debugger shows the cardValue fields with no value.
Empty Widget:
This should work:
class PockerCard extends StatefulWidget {
final String cardValue;
const PockerCard({Key key, this.cardValue}) : super(key: key);
#override
_PockerCardState createState() => _PockerCardState();
}
class _PockerCardState extends State<PockerCard> {
#override
Widget build(BuildContext context) {
return Container(
child: Text(widget.cardValue),
);
}
}
For a StatelessWidget, how can I have a constructor with named arguments and set private final variables after doing certain validations.
class MyWidget extends StatelessWidget {
const MyWidget({bool foo}) : /*do validation e.g. ArgumentError.checkNotNull(foo)*/ _foo = foo;
final bool _foo;
#override
Widget build(BuildContext context) {...}
}
Try this:
class MyWidget extends StatelessWidget {
MyWidget({bool foo})
: assert(foo != null), // validation
_foo = foo; // assigning value
final bool _foo;
#override
Widget build(BuildContext context) {...}
}