I need to be a nullable parameter in a custom widget - flutter

i make a custom widget and using this widget in 7-8 place. i need to add a mask but in widget source said "it cant be null". i dont want to sent null parameter in all usage because i need to use only one place
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class TextFieldWidget extends StatelessWidget {
final text;
final controller;
final validation;
final mask;
final bool maxLength;
const TextFieldWidget({
Key? key,
this.text,
this.validation,
this.controller,
required this.maxLength, this.mask,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return TextFormField(
inputFormatters: [
LengthLimitingTextInputFormatter(maxLength ? 20 : null),
mask
],
validator: validation,
decoration: InputDecoration(
labelText: text,
border: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.grey, width: 0.0),
borderRadius: BorderRadius.circular(10)),
),
);
}
}
i need to be nullable this "mask" parameter. thanks all!

It's a good practice assigning the types of parameters instead of leaving them dynamic as you do. A simple workaround is below :
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class TextFieldWidget extends StatelessWidget {
final text;
final controller;
final validation;
final TextInputFormatter? mask;
final bool maxLength;
const TextFieldWidget({
Key? key,
this.text,
this.validation,
this.controller,
required this.maxLength,
this.mask,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return TextFormField(
inputFormatters: [
LengthLimitingTextInputFormatter(maxLength ? 20 : null),
if (mask != null) mask!
],
validator: validation,
decoration: InputDecoration(
labelText: text,
border: OutlineInputBorder(
borderSide: const BorderSide(color: Colors.grey, width: 0.0),
borderRadius: BorderRadius.circular(10)),
),
);
}
}

Related

How to write styles in flutter as classes

Let's say I have a souple of components using the same styles but I want it to write as classes like in html and css
Is there a way this is possible?
By the way I'm a noob to coding started a year ago I'm 14 years old
I have added an example for read only text field for your reference.
class ReadOnlyTextWidget extends StatefulWidget {
final TextEditingController controller;
final String label;
final Function() onPressedCallback;
const ReadOnlyTextWidget({
required this.controller,
required this.label,
required this.onPressedCallback,
Key? key,
}) : super(key: key);
#override
State<ReadOnlyTextWidget> createState() => _ReadOnlyTextWidgetState();
}
class _ReadOnlyTextWidgetState extends State<ReadOnlyTextWidget> {
#override
Widget build(BuildContext context) {
return TextFormField(
controller: widget.controller,
decoration: InputDecoration(
label: Text(widget.label),
hintText: 'Enter ${widget.label}',
border: const OutlineInputBorder(),
icon: TextButton.icon(
onPressed: widget.onPressedCallback,
label: const Text('Refresh'),
icon: const Icon(Icons.refresh),
)),
readOnly: true,
);
}
}

Flutter checkbox inside textfield

I was wondering how I could recreate the Samsung Notes App. To be more precise I want to have the checkbox functionality within the textfield. See picture below:
Thanks for your support!
I've just tried it myself and this looks like how you want it to look:
TextField(
decoration: InputDecoration(
prefixIcon: Checkbox(value: value, onChanged: (value) {//bool magic here}),
hintText: 'TextField'
),
),
Check out https://api.flutter.dev/flutter/material/InputDecoration-class.html for more InputDecoration() options to prettify things.
if I understood you correctly you can use Textformfield. You can add the checkbox widget to the textformfield prefix parameter. I hope this gives you an idea and helps.
For Example:
class MyHomePage extends StatefulWidget {
final String title;
const MyHomePage({
Key? key,
required this.title,
}) : super(key: key);
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool isChecked = false;
TextEditingController textController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: TextField(
controller:textController,
style:TextStyle(decoration: isChecked ? TextDecoration.lineThrough : TextDecoration.none),
decoration: InputDecoration(
prefixIcon: Checkbox(value:isChecked, onChanged: (value) {
setState(() { isChecked=value!;});
}),
hintText: 'To Do'
),
),
),
);
}
}
Dartpad => https://dartpad.dev/?id=e75b493dae1287757c5e1d77a0dc73f1

I want to set a value including BorderRadius.circular as the default value of the argument of the constructor

I have defined a custom widget for ElevatedButton, and I want to make the shape field optional as shown below and use the initial value when no value is passed, but when I write it as above, the following error occurs. ..
class GradientElevatedButton extends StatelessWidget {
GradientElevatedButton({
Key? key,
required this.onPressed,
required this.child,
required this.colors,
this.shape = RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),//←here
),
}) : super(key: key);
final Widget child;
final void Function() onPressed;
final List<Color> colors;
final OutlinedBorder shape;
//error
The default value of an optional parameter must be constant.
Maybe it means that the BorderRadius.circular constructor is not const,
How should I write if I want to use the following OutlinedBorder as the default value?
RoundedRectangleBorder (
borderRadius: BorderRadius.circular (30),
)
BorderRadius.circular is not a const constructor, so you cannot use it as a default value of a const constructor.
However, if you look at the implementation:
/// Creates a border radius where all radii are [Radius.circular(radius)].
BorderRadius.circular(double radius) : this.all(
Radius.circular(radius),
);
It uses BorderRadius.all and Radius.circular and both of them are const constructor.
So you can replace
BorderRadius.circular(shape)
with
BorderRadius.all(Radius.circular(30))
Here is your updated code sample:
```class GradientElevatedButton extends StatelessWidget {
GradientElevatedButton({
Key? key,
required this.onPressed,
required this.child,
required this.colors,
this.shape = const RoundedRectangleBorder( // <- Don't forget the const keyword
borderRadius: BorderRadius.all(Radius.circular(30)),//←here
),
}) : super(key: key);
final Widget child;
final void Function() onPressed;
final List<Color> colors;
final OutlinedBorder shape;
I think this is not what you want, but sometime it helps others.
import 'package:flutter/material.dart';
class GradientElevatedbutton extends StatelessWidget {
const GradientElevatedbutton({
Key? key,
required this.onPressed,
required this.child,
required this.colors,
this.shape = 30,
}) : super(key: key);
final Widget child;
final void Function() onPressed;
final List<Color> colors;
final double shape;
#override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(shape),
),
),
child: Text('click'),
);
}
}
This part of your code:
this.shape = RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
must be change to:
this.shape = const RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),

How to extract TextFormField as reusable widget in flutter

I want to make my flutter project highly manageable, apply clean code and maintain DRY concept strictly. There are a lot of input elements in any flutter project. So I want to make this element as a separate widget so that if I want to change in future then I will change in one place. Here is my approach:
import 'package:flutter/material.dart';
import '../utility/validatation.dart';
class RegistrationPage extends StatefulWidget {
static const String routeName = '/registrationPage';
#override
State<RegistrationPage> createState() => _RegistrationPageState();
}
class _RegistrationPageState extends State<RegistrationPage> {
final _formKey = GlobalKey<FormState>();
final TextEditingController nameInput = TextEditingController();
final TextEditingController businessName = TextEditingController();
final TextEditingController productTypeId = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: new Form(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [
Container(
height: 70,
margin: EdgeInsets.only(bottom: 50),
child: Image(image: AssetImage('assets/logo.png')),
),
Padding(
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 30.0),
child: TextInput(inputController: nameInput, label: 'আপনার নাম'),
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_register(context);
}
},
child: Text('Next'),
)
]),
),
);
}
void _register(BuildContext context) {}
}
class TextInput extends StatelessWidget {
const TextInput({
Key? key,
required this.inputController,
required this.label,
}) : super(key: key);
final TextEditingController inputController;
final String label;
#override
Widget build(BuildContext context) {
return TextFormField(
controller: inputController,
keyboardType: TextInputType.text,
decoration: const InputDecoration(
border: UnderlineInputBorder(),
prefixIcon: Icon(Icons.phone),
labelText: label,
),
validator: (value) {
return Validation.required(value);
},
);
}
}
But I got this error:
What is wrong in my code? Is there any problem in my approach or should I stop thinking to refactor my code as I do? Please also suggest if there is any smarter way to make code more clean and manageable.
Oh I see so you have this
class TextInput extends StatelessWidget {
const TextInput({
Key? key,
required this.inputController,
required this.label,
}) : super(key: key);
final TextEditingController inputController;
final String label;
#override
Widget build(BuildContext context) {
return TextFormField(
controller: inputController,
keyboardType: TextInputType.text,
// Notice the const here right?
// So the idea is that decoration objects could rebuild to either change one thing or the other, so 'label' here cannot be a constant
//So to solve this InputDecoration should not have const.
decoration: const InputDecoration(
border: UnderlineInputBorder(),
prefixIcon: Icon(Icons.phone),
labelText: label,
),
validator: (value) {
return Validation.required(value);
},
);
}
}
Since you are using a variable in InputDecoration, you should not declare InputDecoration with const keyword.

Flutter/Dart: Pass Parameters to a Stateful Widget?

I need to call pass my title and oldtitle parameters to my EditPage Stateful widget. But if I do this;
class EditPage extends StatefulWidget {
String title;
String oldtitle;
EditPage({this.title, this.oldtitle})
The strings are not available to the build unless I call it them as widget.title and widget.oldtitle.
But I'm using a textfield within a form that doesn't seem to work right if I use these widgets.
Here's the form code:
Container(
child: TextField(
decoration: new InputDecoration(
hintText: widget.oldtitle,
contentPadding: new EdgeInsets.all(1.0),
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[300],
),
keyboardType: TextInputType.text,
autocorrect: false,
onChanged: (titleText) {
setState(() {
widget.title= titleText;
});
},
),
),
But then if I do this;
class _EditPageState extends State<EditPage> {
String title;
String oldtitle;
EditPage({this.title, this.oldtitle})
I can't pass the title parameter to it from another screen. IE:
`EditPage(title:mytitle, oldtitle:myoldtitle);`
So What's the correct way to pass a parameter to a Stateful widget?
You should never pass the variables to the state directly, since it does not guarantee that widget will get rebuilt when state will be updated. You should accept parameters via your stateful widget and access them from the state itself via widget.variable.
Example:
class TestWidget extends StatefulWidget {
final String variable;
TestWidget({Key key, #required this.variable}) : super(key: key);
#override
_TestWidgetState createState() => _TestWidgetState();
}
class _TestWidgetState extends State<TestWidget> {
#override
Widget build(BuildContext context) {
return Container(
child: Center(
// Accessing the variables passed into the StatefulWidget.
child: Text(widget.variable),
),
);
}
}
Looks like the solution was to separate the title from the oldtitle;
class EditPage extends StatefulWidget {
String oldtitle;
EditPage({this.oldtitle})
and then;
class _EditPageState extends State<EditPage> {
String title;
So now for the form;
Container(
child: TextField(
decoration: new InputDecoration(
hintText: widget.oldtitle,
contentPadding: new EdgeInsets.all(1.0),
border: InputBorder.none,
filled: true,
fillColor: Colors.grey[300],
),
keyboardType: TextInputType.text,
autocorrect: false,
onChanged: (titleText) {
setState(() {
title= titleText;
});
},
),
),