Hide a Field on Flutter Form Builder - flutter

Let's say we want to pass an ID on form submission but we don't want the users to see it, on flutter_form_builder: ^7.1.1 there is no option to hide fields, any workaround?

I just found out that flutter_form_builder: ^7.1.1 offers to build your own custom field, so if we want to make a hidden field, we just return a SizedBox.shrink() on builder and set the initial value on FormBuilderField.Heres a sample code.
Widget taskIDField() {
return FormBuilderField(
name: "task_id",
enabled: false,
initialValue: widget.task?.id.toString(),
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
]),
builder: (FormFieldState<dynamic> field) {
//Empty widget
return const SizedBox.shrink();
},
);
}

Related

How make default selection in FormBuilderDropdown list in flutter?

I am having a multiple FormBuilder dropdown in my flutter app. all of them are dependent dropdown.
i want to implement something like this:
the first of the main parent dropdown value should be auto fill and hence all other are filled or selected depending on the parents selection.
I can see the text filled in all the dropdown but as it is the dependent it is disabled for first dropdown to be clicked once.
How to fix this issue?
in the below screenshot we can see that the data is filled or been selected in every dropdown but second dropdown is still been disabled. it only gets enabled after clicking or selecting the value in first dropdown. enter image description here
Here is my code for first dropdown
padding: const EdgeInsets.all(12.0),
child: FormBuilderDropdown(
name: 'City',
decoration: InputDecoration(
labelText: 'City',
),
allowClear: true,
hint: Text(widget.callLocationModel.CityName),
initialValue: citySelected,
validator: FormBuilderValidators.compose(
[FormBuilderValidators.required(context)]),
items: cityList
.map((citySelected) => DropdownMenuItem(
value: cityChoosen,
child:new Text('$citySelected'),
))
.toList(),
onChanged: (String value){
setState(() {
citySelected= value;
//this fuction calls my second dropdown depending on first dropdown value selection
fetchSite(citySelected);
});
},
),
),
I assume all this layout is done in a stageful widget, which has a variable in it’s state for each selected value (when it’s selected). You may override initState member function and set the initial values there, so when the widget is built for the first time it will have those values preselected.

How to write data in firebase cloud firestore with data type using flutter

When saving data to the Firebase database I want every data to be saved according to its data type. But my all data is stored in String. How can I do it in flutter... like Amount will be int, Through will be String
[
here is my function
sandDataToDB() async {
CollectionReference _collectionReferance =
FirebaseFirestore.instance.collection("Use-of-fund");
return _collectionReferance
.doc()
.set({
"Details of Sector": _DetailsofSectorController.text,
"Through": _ThroughController.text,
"Amount": _AmountController.text,
"Date": _DateController.text,
})
.then((value) => dialog())
.catchError((error) => Fluttertoast.showToast(msg: "something wrong"));
}
here is all code
customAdminTextField(
"Details of Sector", _DetailsofSectorController),
customAdminTextField("Through", _ThroughController),
customAdminTextField("Amount", _AmountController),
customAdminTextField("Date", _DateController),
const SizedBox(
height: 10,
),
customSubmitButton("Submit ", () {
sandDataToDB();
})
You have to parse your data. An example for an integer:
...
"Amount": int.parse(_AmountController.text),
...
Here you can find the supported data types.
According to your question, you might be using the controller in TextFormField, you can get the value of the TextFormField.
This widget covers a TextField widget in a FormField for convenience.
It is not necessary to have a Form ancestor. The Form merely simplifies the process of saving, resetting, or validating numerous fields at the same time. To use without a Form, supply a GlobalKey to the constructor and save or reset the form field with GlobalKey.currentState.
TextEditingController.text defines the initialValue when a controller is defined. A controller should be given if this FormField is part of a scrolling container that generates its children lazily, such as a ListView or a CustomScrollView.
A stateful widget ancestor of the scrolling container should handle the controller's lifetime.
Example code:
TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.person),
hintText: 'What do people call you?',
labelText: 'Name *',
),
onSaved: (String? value) {
// This optional block of code can be used to run
// code when the user saves the form.
},
validator: (String? value) {
return (value != null && value.contains('#')) ? 'Do not use the # char.' : null;
},
)
You can also use the onSubmitted parameter in TextFormField. Like: onSubmitted: (String value)
Additionally, you can use something like this in the following code:
_formKey.currentState.save(); calls the onSaved() on each textFormField item, which gives all the fields a value and allows you to utilize them as needed.

Flutter UI only changes if i manualy refresh the page

I have two forms in a tab bar. I'm using Getx for state management. All fields in those forms listen to a .obs variable. The forms fields are updating to the variable changes. How ever one field only reflect changes when that page is revisited.
I'm using this variables
final _countryCode = ''.obs
String get countryCode => _countryCode.value;
final _phone = ''.obs
String get phone => _countryCode.value;
These variable are updated on init.
void onInit(){
super.onInit();
_countryCode(user.countryCode); // assign country code
_phone(user.number); // assign number
}
return Obx(() => IntlPhoneField(
final UserController _controller = Get.find()
enabled: true,
showCountryFlag: false,
iconPosition: IconPosition.trailing,
autoValidate: false,
initialValue: _controller.initialPhoneNumber,
initialCountryCode: _controller.userCountryCode,
);
How ever this field is not updating on init. but updates after that page is revisited.. What's causing this? All other fields are updating without any issue. But this one will update only if its revisited. How can i solve this??
It's better to use GetBuilder instead of Obx.
GetBuilder(
init: UserController,
builder: (_controller){
return IntlPhoneField(
enabled: true,
showCountryFlag: false,
iconPosition: IconPosition.trailing,
autoValidate: false,
initialValue: _controller.initialPhoneNumber,
initialCountryCode: _controller.userCountryCode,
);}),
There is also an initstate attribute for GetBuilder,
You can get more details from here.

Updating dropdown value without rebuild all widget tree Flutter

this is my first question at StackOverflow, I'm a flutter and dart newbie so I hope to get some help from here.
I'm coding an app that use a TableCalendar to make appointments, I load data in some dates in the calendar using the "events" property, so when I pick any date, if that date has data I load its data in a Dropdown button, I'm using a Stream broadcast() to listen to every time I pick a date so dropdown items change according to the date.
Up to this point I have no problem, the problem is when my dropdown items are ready and I try to pick another value inside the dropdown menu, since the value needs to be updated using OnChanged property, I need to call the setState, but when I do that all the widget tree is rebuilt, and if I don't use the setState obviously the value doesn't change.
I need to update only the dropdown menu item without redrawing all the widget trees keeping the actual state of all the other widgets except the dropdown value and I've been looking from here and there for any solution but I don't find it.
The TableCalendar and the DropdownButton are inside a Listview, the data source is a JSON file, I'm using a Future Builder to build the ListView and a StreamBuilder to build the DropdownButton.
This is the dropdown code:
StreamBuilder(
stream: streamHora.stream,
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (!snapshot.hasData) {
return DropdownButton<String>(
icon: Icon(Icons.arrow_drop_down),
style: _textStyle(Colors.black, 15.0),
items: [],
onChanged: (value) {},
value: "",
);
}
return DropdownButton<String>(
icon: Icon(Icons.arrow_drop_down),
style: _textStyle(Colors.black, 15.0),
items: snapshot.data,
onChanged: (String value) {
setState(() {
_dropdownHoraValue = value;
});
},
value: _dropdownHoraValue,
);
},
),
Any idea or suggestion will be very appreciated.

What is the difference between TextFormField and TextField?

I am new to Flutter (and Dart) and when trying to build a form to edit an object I searched online for examples and tutorials, and I saw both of these used.
What is the difference between the two? Which one should I use?
If you making a Form where you require save, reset, or validate
operations- use TextFormField. Else For Simple user input capture
TextField is sufficient.
TextFormField, which integrates with the Form widget.
This is a convenience widget that wraps a TextField widget in a FormField.
A Form ancestor is not required. The Form simply makes it easier to save, reset, or validate multiple fields at once.
To use without a Form, pass a GlobalKey to the constructor and use GlobalKey.currentState to save or reset the form field.
sample:
TextFormField(
autovalidateMode: AutovalidateMode.always
decoration: const InputDecoration(
icon: Icon(Icons.person),
hintText: 'What do people call you?',
labelText: 'Name *',
),
onSaved: (String value) {
// This optional block of code can be used to run
// code when the user saves the form.
},
validator: (String value) {
return value.contains('#') ? 'Do not use the # char.' : null;
},
)
TextField, which is the underlying text field without the Form integration.
The text field calls the onChanged callback whenever the user changes the text in the field. If the user indicates that they are done typing in the field (e.g., by pressing a button on the soft keyboard), the text field calls the onSubmitted callback.
Short answer
If you don't know what you need, then use a TextField. This is the most basic Flutter widget for getting text input from a user. It's the one you should master first.
TextField
Using a TextField is an easy way to allow user input.
TextField(
decoration: InputDecoration(
hintText: 'Name'
),
);
To get the text that the user entered, you can either get notified every time there is a change like this:
TextField(
decoration: InputDecoration(
hintText: 'Name'
),
onChanged: (text) {
// do something with text
},
),
Or you can use a TextEditingController, as described here. This will give you access to the text state.
TextFormField
If you find yourself needing to validate user text input before you save it, you might consider using a TextFormField. Imagine something like this:
There are lots of validation checks that you might want to do on a username and password.
Of course, you could still just use a couple TextFields, but TextFormField has extra builtin functionality that will make your life easier. Generally, you will only use a TextFormField when you are using it inside of a Form widget (though that isn't a strict requirement).
Here is a stripped down example from the documentation:
class MyCustomForm extends StatefulWidget {
#override
MyCustomFormState createState() {
return MyCustomFormState();
}
}
class MyCustomFormState extends State<MyCustomForm> {
final _formKey = GlobalKey<FormState>();
#override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: <Widget>[
TextFormField(
validator: (value) {
// validation logic
},
),
RaisedButton(
child: Text('Submit'),
onPressed: () {
if (_formKey.currentState.validate()) {
// text in form is valid
}
},
),
],
),
);
}
}
See also
Realistic Forms in Flutter — Part 1
Forms with Flutter
TextField is a simple text field. (you don't care about user input)
TextFormField is a text field to be used in a form (you care about user input).
If you don't need to validate TextField.
If you need to validate user input, use TextFormField with validator.
TextFormField vs. TextField
TextFormField returns a TextField, but wraps the TextField with extra functionality you can use through a Form and also without (such as reset, validation, save, etc.).
Generally, you want to use TextFormField unless writing boiler-plate code is your thing.
How does TextFormField work? What can it do?
TextFormField extends FormField class, (a StatefulWidget).
FormField objects do a special thing when they are instantiated: they look up the widget tree for a Form and register themselves with that Form.
After registration, these FormField widgets can be changed by that parent Form.
Form is also a StatefulWidget. It has a FormState object.
FormState can get & set data on any/allFormFields registered to it.
For example to clear the entire form we can call reset() on FormState and FormState will iterate through all child FormFields registered, resetting each FormField to its initialValue (null by default).
Validation is another common use case for putting several FormField like TextFormField inside Form/FormState. This allows multiple fields to be validated with a single validate() call on the Form.
How? FormState has a validate() method that iterates through each registered FormField and calls that FormField's validate() method. Much more convenient calling validate() once on Form than you manually keeping track of all TextField and validating each one separately with custom code.
Details
How does a TextFormField register itself with a Form?
FormField (base class of TextFormField, etc.) make a call within their build() method:
Form.of(context)?._register(this);
In English this means:
Search up my context hierarchy until we find a Form widget (if any) and call that form's register method on myself.
The ? is in case there is no Form widget parent. The _register call will only be run if there is a Form & FormState somewhere above.
How does Form.of(context)?._register(this) work?
Form & FormState sneakily use InheritedWidget.
In FormState.build() you'll see this code:
return WillPopScope(
onWillPop: widget.onWillPop,
child: _FormScope( // ← sneaky
formState: this,
generation: _generation,
child: widget.child,
),
);
Looking at _FormScope we see:
class _FormScope extends InheritedWidget
When a parent widget is an InheritedWidget, any child can find that parent using a special "find me a parent of this exact Type" method.
Here's how that "find me" method is used/exposed inside Form as a static method we can call from anywhere:
static FormState of(BuildContext context) {
final _FormScope scope = context.dependOnInheritedWidgetOfExactType<_FormScope>();
return scope?._formState;
}
The naming of that method dependOnInheritedWidgetOfExactType is a bit tricky. It'd be more readable as findInheritedWidgetOfExactType, but it does more than just find. (We can trigger rebuilds of Form through children that have registered as dependOn this FormState).
Summary
TextFormField is the deluxe package, air-conditioned, Bluetooth-connected 8-speaker stereo version of TextField. It includes a lot of common functionality you would use when accepting user-entered information.
I think this might be the most concise and simple explanation about the differences between the two.
From the material library:
TextField: A material design text field.
TextFormField: A FormField that contains a TextField.
Similarly, you can wrap FormField around any cupertino input component such as CupertinoTextField
Below is an example about a custom CheckboxFormField, which is a FormField that wraps around the material design component Checkbox:
// A custom CheckboxFormField, which is similar to the built-in TextFormField
bool agreedToTerms = false;
FormField(
initialValue: false,
validator: (value) {
if (value == false) {
return 'You must agree to the terms of service.';
}
return null;
},
builder: (FormFieldState formFieldState) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Checkbox(
value: agreedToTerms,
onChanged: (value) {
// When the value of the checkbox changes,
// update the FormFieldState so the form is
// re-validated.
formFieldState.didChange(value);
setState(() {
agreedToTerms = value;
});
},
),
Text(
'I agree to the terms of service.',
style: Theme.of(context).textTheme.subtitle1,
),
],
),
if (!formFieldState.isValid)
Text(
formFieldState.errorText ?? "",
style: Theme.of(context)
.textTheme
.caption
.copyWith(color: Theme.of(context).errorColor),
),
],
);
},
),
Rule of thumb: If your box only have a single input field, just use the raw material input like TextField (FormField is a bit overkill in this case though). If your box has many input fields, you need to wrap each one of them in a FormField, and then integrate all of them to the Form widget to reap the benefits of validating and saving all form fields at once.
Extra tip: If u have a TextField wrapped in a FormField that doesn't allow the user to enter any text such as a CupertinoPickerFormField or a SimpleDialogFormField that offers the user a choice between several options (which is basically a material SimpleDialog widget wrapped in a FormField), just simply use the hintText param of InputDecoration without using TextEditingController to manipulate text. Make the hint text have the same color as the normal input text with hintStyle: const TextStyle(color: Color(0xdd000000)).
This video from Flutter Europe will help you master forms in Flutter in no time.