Change textfield value with firebase realtime database value - flutter

I want to change two textfields value via firebase realtime database value in Flutter not sure how to do it
this is my code I am using Getx controller that is why a little confused
i am a beginner so ignore bad code
for Firebase :
static void readData() async
{
DatabaseReference dataRef = FirebaseDatabase.instance
.ref()
.child("test");
dataRef.once().then((snap)
{
if(snap.snapshot.value != null)
{
dataModelInfo = DataModel.fromSnapshot(snap.snapshot);
BlockController().fheight = dataModelInfo!.height.toString();
BlockController().flength = dataModelInfo!.length.toString();
print("height ="+ dataModelInfo!.height.toString());
print("length ="+ dataModelInfo!.length.toString());
}
});
}
For Textfields :
class BlockController extends GetxController{
final WallheightController = TextEditingController();
final WalllengthController = TextEditingController();
}
want to update text field data after retrieving from firebase
class SidesField extends StatelessWidget {
SidesField({
Key? key,
required this.labelText,
required this.controller, required Map Function(dynamic text) onChanged,
}) : super(key: key);
final String labelText;
final TextEditingController controller;
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
keyboardType: const TextInputType.numberWithOptions(decimal: true),
controller: controller,
decoration: InputDecoration(
labelText: labelText,
labelStyle: const TextStyle(color: kPurpleColor),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: kPurpleColor,
width: 3,
),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(
color: Colors.grey,
),
),
),
validator:(value){
if(value!.isEmpty){
return "Enter This Field";
}
return null;
},
),
);
}
}
Please tell my how to change value of text field after taking data from firebase realtime database

Related

How can I make a Stateless TextInputWidget with a optional Icon as input argument?

I am trying to create a RoundedInputField as a StatelessWidget. I am still learning both Dart and Flutter but I am a bit stuck at the moment. So where it all started is that I want to optionally choose a prefixIcon from outside the class. I created a helper function buildInputDecorator in order to handle the creation of InputDecoration based on iconData is set or not. I have a couple of compilation errors that I am not sure how to tackle. I have added the errors as comments.
My code is:
import 'package:flutter/material.dart';
class RoundedInputField extends StatelessWidget {
final IconData? iconData;
const RoundedInputField({super.key, this.iconData});
InputDecoration buildInputDecorator(String hint) {
if (iconData != null) {
return const InputDecoration(
hintText: hint, //Invalid constant value.dart(invalid_constant)
prefixIcon: Icon(iconData), //Arguments of a constant creation must be constant expressions.
);
}
return const InputDecoration(
hintText: hint, //Invalid constant value.dart(invalid_constant)
);
}
#override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
color: Color.fromRGBO(73, 152, 203, 1),
),
padding: const EdgeInsets.fromLTRB(10.0, 0, 0, 10.0),
child: const TextField(
decoration: buildInputDecorator("Email"), //Invalid constant value.dart(invalid_constant)
),
);
}
}
I try your code, why not just like this instead of making a function :
import 'package:flutter/material.dart';
class RoundedInputField extends StatelessWidget {
final IconData? iconData;
final String? hint;
const RoundedInputField({super.key, this.iconData, this.hint});
#override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5.0)),
color: Color.fromRGBO(73, 152, 203, 1),
),
padding: const EdgeInsets.fromLTRB(10.0, 0, 0, 10.0),
child: TextField(
decoration: InputDecoration(
hintText: hint,
prefixIcon: iconData != null ? Icon(iconData) : null
),
),
);
}
}

How can I make FormBuilderTextField validators reusable?

So I am making a sign up page in Flutter. I'm gonna use this "flutter_form_builder" and "form_builder_validators" packages. I will make the textfields reusable to save time, and everything works, except the validators.
This is my reusable widget:
class MyFormBuilderTextField extends StatelessWidget {
final String name;
final Color inputTextColor;
final String labelText;
final Color labelColor;
final bool filled;
final Color fillColor;
final double borderRadius;
final Color enabledBorderColor;
final Color focusedBorderColor;
final FormFieldValidator<String> validators;
MyFormBuilderTextField({
required this.name,
this.inputTextColor = const Color(0xFFFFFFFF),
required this.labelText,
this.labelColor = Colors.white54,
this.filled = true,
this.fillColor = const Color(0xFF131313),
this.borderRadius = 10.0,
this.enabledBorderColor = Colors.white12,
this.focusedBorderColor = const Color(0xFFF57B3B),
required this.validators,
});
#override
Widget build(BuildContext context) {
return FormBuilderTextField(
name: name,
style: TextStyle(color: inputTextColor),
decoration: InputDecoration(
labelText: labelText,
labelStyle: TextStyle(color: labelColor),
filled: filled,
fillColor: fillColor,
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(borderRadius),
borderSide: BorderSide(color: enabledBorderColor),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(borderRadius),
borderSide: BorderSide(color: focusedBorderColor),
),
),
validator:validators,
);
}
}
This is how I tried implementing it:
class MyFormBuilder extends StatefulWidget {
#override
State<MyFormBuilder> createState() => _MyFormBuilderState();
}
class _MyFormBuilderState extends State<MyFormBuilder> {
final _formKey = GlobalKey<FormBuilderState>();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Color(0xFF070707),
body: _buildContent(),
);
}
Widget _buildContent() {
return SingleChildScrollView(
padding: EdgeInsets.all(24.0),
child: FormBuilder(
key: _formKey,
child: Column(
children: <Widget>[
SizedBox(height: 30.0),
MyFormBuilderTextField(
name: 'password',
labelText: 'Password',
validators: [
FormBuilderValidators.min(8),
FormBuilderValidators.required(),
],
),
],
),
)
);
}
}
I am getting this error:
The argument type 'String? Function(String?)' can't be assigned to the parameter type 'List<String? Function(String?)>'.dartargument_type_not_assignable
How can I make the validators reusable?

Flutter - Reusable Widget TextFormField - validation does not work

I am using a reusable widget and trying to pass a validation before the form is submitted.
But, I am not getting the error message that I should get. I have read the code several times, but do not find where is the problem. If you can have a quick look and tell me what I am missing it would be great.
import 'package:flutter/material.dart';
class TextFormFieldWidget extends StatefulWidget {
String hintText;
TextEditingController controller;
int maxLength;
int maxLines;
// Function onChanged;
TextInputAction? actionKeyboard;
String? parametersValidate;
String? defaultText;
String? labelText;
TextInputType? textInputType;
FocusNode? focusNode;
bool? obscureText;
Widget? prefixIcon;
Function onSubmitField;
Function? onFieldTap;
Function? functionValidate;
String? decoration;
String? validator;
//final dynamic Function(String?)? onChanged;
TextFormFieldWidget({
Key? key,
required this.hintText,
required this.controller,
required this.onSubmitField,
required this.maxLength,
required this.maxLines,
// required this.onChanged,
this.labelText,
this.validator,
this.parametersValidate,
this.textInputType,
this.onFieldTap,
this.defaultText,
this.actionKeyboard,
this.prefixIcon,
this.focusNode,
this.obscureText,
this.functionValidate,
this.decoration,
}) : super(key: key);
#override
_TextFormFieldWidgetState createState() => _TextFormFieldWidgetState();
}
class _TextFormFieldWidgetState extends State<TextFormFieldWidget> {
double bottomPaddingToError = 12;
#override
Widget build(BuildContext context) {
return Theme(
data: Theme.of(context).copyWith(
primaryColor: Colors.black,
),
child: TextFormField(
cursorColor: Colors.black,
// obscureText: widget.obscureText,
keyboardType: widget.textInputType,
textInputAction: widget.actionKeyboard,
focusNode: widget.focusNode,
maxLength: widget.maxLength,
maxLines: widget.maxLines,
style: const TextStyle(
color: Colors.black,
fontSize: 16.0,
fontWeight: FontWeight.w200,
fontStyle: FontStyle.normal,
letterSpacing: 1.2,
),
initialValue: widget.defaultText,
decoration: InputDecoration(
prefixIcon: widget.prefixIcon,
hintText: widget.hintText,
// labelText: widget.decoration!,
// enabledBorder: const OutlineInputBorder(
// borderSide: BorderSide(color: Colors.black),
// ),
// focusedBorder: const OutlineInputBorder(
// borderSide: BorderSide(color: Colors.black),
// ),
hintStyle: const TextStyle(
color: Colors.grey,
fontSize: 14.0,
fontWeight: FontWeight.w300,
fontStyle: FontStyle.normal,
letterSpacing: 1.2,
),
contentPadding: EdgeInsets.only(
top: 12, bottom: bottomPaddingToError, left: 8.0, right: 8.0),
isDense: true,
errorStyle: const TextStyle(
color: Colors.red,
fontSize: 12.0,
fontWeight: FontWeight.w300,
fontStyle: FontStyle.normal,
letterSpacing: 1.2,
),
errorBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusedErrorBorder: const OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
),
controller: widget.controller,
validator: (value) {
if (widget.functionValidate != null) {
String resultValidate =
widget.functionValidate!(value, widget.parametersValidate);
if (resultValidate != null) {
return resultValidate;
}
}
return null;
},
onFieldSubmitted: (value) {
if (widget.onSubmitField != null) widget.onSubmitField();
},
onTap: () {
if (widget.onFieldTap != null) widget.onFieldTap!();
},
),
);
}
}
String? commonValidation(String value, String messageError) {
var required = requiredValidator(value, messageError);
if (required != null) {
return required;
}
return null;
}
String? requiredValidator(value, messageError) {
if (value.isEmpty) {
return messageError;
}
return null;
}
void changeFocus(
BuildContext context, FocusNode currentFocus, FocusNode nextFocus) {
currentFocus.unfocus();
FocusScope.of(context).requestFocus(nextFocus);
}
Widget
Widget _buildTextFormField(String myHintText,TextEditingController myController,
int length,int lines,String myContent) {
return TextFormFieldWidget(
hintText: myHintText,
decoration: 'Test 33',
controller: myController,
maxLength: length,
maxLines: lines,
onSubmitField: () {},
validator:checkFieldEmpty( myContent),
);
String? checkFieldEmpty(String? fieldContent) { //<-- add String? as a return type
if(fieldContent!.isEmpty) {
return 'Field empty => Please, change this.';
}
return null;
View
SingleChildScrollView(
child: Form(
key: _addFirstTaskFormKey,
child: Column(
children: [
_buildTextFormField('Task Name',taskNameController,100,3,taskNameController.text),
ElevatedButton(
onPressed: (){
if(_addFirstTaskFormKey.currentState!.validate()){
print ('validated');
//taskItems.taskName = taskNameController.text;
//taskItems.notes = notesController.text;
}
}, child: const Text('Press'),
),
I think you're relatively new to flutter, don't worry I got you,
FormValidators are used to validate multiple fields declared inside a Form Widget.
Form widget uses a global Form key
declared Like this,
final _formKey = GlobalKey<FormState>();
and fields
Like this,
child: Form(child:Column(children:[
TextFormField(controller:controller),
TextFormField(controller:controller),
],),),
so when you need to validate fields just call,
_formKey.validate();
in the case above you are making a CustomTextFormField
you don't necessarily need to make it a stateful widget,
use StateLess Widget instead,
class CustomTextFormField extends StateLessWidget {
final TextInputType? keyboardType;
final TextEditingController? controller;
final FormFieldValidator<String>? validator;
final ValueChanged<String?>? onSaved;
final Function(String)? onChanged;
final VoidCallback? onTap;
const CustomTextFormField(
this.keyboardType,
this.controller,
this.validator,
this.onSaved,
this.onChanged,
this.onTap,
);
#override
Widget build(BuildContext context) {
return TextFormField(
keyboardType: keyboardType,
validator: validator,
autovalidateMode: autoValidateMode,
onSaved: onSaved,
onChanged: onChanged,
);
}
and use it like this
CustomTextFormField(
validator: (String? val) {
if(val==null) {
return "Value cannot be empty";
}
return null;
},
),
add any other validation that you may want to apply
and on save button call
if(_formKey.currentState.validate()) {
//SaveData
}else {
print("Validation Error")
}
This may be the problem. You're using null values. Flutter has Sound null safety so this means you can't set variables to null. I'm really curious, does your code even run?
Solution:
Scrap your validator and read through the Flutter Docs. They'll walk you through building a Form with validation here
validator: (value) {
if (widget.functionValidate != null) {
String resultValidate =
widget.functionValidate!(value, widget.parametersValidate);
if (resultValidate != null) {
return resultValidate;
}
}
return null;
},
onFieldSubmitted: (value) {
if (widget.onSubmitField != null) widget.onSubmitField();
},
onTap: () {
if (widget.onFieldTap != null) widget.onFieldTap!();
},
),
);
}

Working With Seperate Files in Flutter/Dart

I am newbie at Dart and OOP.I have one input.dart file for Text Form Fields and login.dart file to conduct login.My problem is I want to acces text controller (located in input.dart) from login.dart.
I created getter method to obtain, (controller.text) data but I have encountered with Initilazation Error.
How Can I acces controller text(which is basically user input) from another file?
input.dart
class InputAlanState extends State<InputAlan> {
late TextEditingController _emailKontroller;
late TextEditingController _sifreKontroller;
#override
void initState() {
super.initState();
_emailKontroller = TextEditingController();
_sifreKontroller = TextEditingController();
}
#override
void dispose() {
_emailKontroller.dispose();
_sifreKontroller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
if (widget.tur == "email") {
return Padding(
padding: const EdgeInsets.only(top: 50, left: 20, right: 20),
child: TextFormField(
controller: _emailKontroller,
autofocus: true,
decoration: const InputDecoration(
labelText: "E - Mail",
hintText: "E-Mail",
prefixIcon: Icon(Icons.email_outlined),
suffixIcon: Icon(Icons.lock),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)))),
),
);
} else if (widget.tur == "sifre") {
return Padding(
padding:
const EdgeInsets.only(top: 40, left: 20, right: 20, bottom: 15),
child: TextFormField(
controller: _sifreKontroller,
obscureText: true,
decoration: const InputDecoration(
labelText: "Password",
hintText: "Password",
prefixIcon: Icon(Icons.password_sharp),
suffixIcon: Icon(Icons.lock),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)))),
),
);
} else {
return Padding(
padding: const EdgeInsets.only(top: 50, left: 20, right: 20),
child: TextFormField(
decoration: const InputDecoration(
labelText: "E - Mail",
hintText: "E-Mail",
prefixIcon: Icon(Icons.email_outlined),
suffixIcon: Icon(Icons.lock),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)))),
),
);
}
}
}
login.py
Widget build(BuildContext context) {
return OutlinedButton(
onPressed: () {
InputAlan inputAlan = InputAlan("email");
String email = inputAlan.email;
String password = inputAlan.sifre;
Login login = login(email, sifre);
girisYap.girisYap(context);
},
child: const Text("SIGN IN"),
style: OutlinedButton.styleFrom(
primary: const Color(0xFF166FC0),
side: const BorderSide(color: Color(0xFF0FA9EA), width: 2),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)))),
);
}
}
to access variables from another state (in your case from InputAlanState) in flutter you have multiple options, the simplest way would be to use a GlobalKey, so in your code you can access InputAlanState's controllers from your login you can use this code in your OutlinedButton:
GlobalKey<InputAlanState> myKey = GlobalKey();
myKey.currentState!._emailKontroller; //here
You're putting a widget in a function parameter. In this way the widget cannot be rendered and it just can't work. I suggest you take a look at how to build flutter layouts to grasp the basics.
You probably want to build something like this:
enum Field { mail, password }
class MyApp extends StatelessWidget {
final TextEditingController mailController = TextEditingController();
final TextEditingController passwordController = TextEditingController();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
children: [
InputAlan(fieldType: Field.mail, textEditingController: mailController,),
InputAlan(fieldType: Field.password, textEditingController: passwordController,),
OutlinedButton(
onPressed: () {
String email = mailController.text;
String sifre = passwordController.text;
// Login login = login(email, sifre);
// girisYap.girisYap(context);
},
child: const Text("SIGN IN"),
style: OutlinedButton.styleFrom(
primary: const Color(0xFF166FC0),
side: const BorderSide(color: Color(0xFF0FA9EA), width: 2),
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)))),
),
],
)
),
);
}
}
TextField widget
class InputAlan extends StatefulWidget {
const InputAlan({
Key? key,
required this.fieldType,
required this.textEditingController,
}) : super(key: key);
final Field fieldType;
final TextEditingController textEditingController;
#override
State<InputAlan> createState() => _InputAlanState();
}
class _InputAlanState extends State<InputAlan> {
#override
Widget build(BuildContext context) {
final isMailField = widget.fieldType == Field.mail;
return Padding(
padding: const EdgeInsets.only(top: 50, left: 20, right: 20),
child: TextFormField(
controller: widget.textEditingController,
autofocus: widget.fieldType == Field.mail,
obscureText: !isMailField,
decoration: InputDecoration(
labelText: isMailField ? "E - Mail" : "Password",
hintText: isMailField ? "E-Mail" : "Password",
prefixIcon:
Icon(isMailField ? Icons.email_outlined : Icons.password_sharp),
suffixIcon: const Icon(Icons.lock),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(20.0)),
)),
),
);
}
}

should Bloc pattern be used for flutter textfield and if yes how?

So I'm new to Bloc but I understand how it works from previously working on native android development, but what I'm trying to understand is should it be implemented to create something like a TextField. Now, keep in mind that I am trying to reuse this TextField multiple times and I want the bloc pattern to dynamically validate the input but should I implement it completely like handle the text inputted by the user?
what I've done is I've created a simple bloc pattern for the text field to handle the user input but it does not save the values from time to time it overwrites the previous value and the cursor keeps moving to the beginning of the text
import 'dart:math';
import 'package:competitionapp/data_model/events/formTextFieldEvent.dart';
import 'package:competitionapp/data_model/states/formTextFieldState.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
FormTextFieldBloc bloc = FormTextFieldBloc();
class FormTextFieldBloc extends Bloc<FormTextFieldEvent, FormTextFieldState> {
void onChanged(String value) {
if (value == null || value.isEmpty)
// todo change to handle errors
this.add(TextChangedEvent("error"));
else
this.add(TextChangedEvent(value));
}
#override
FormTextFieldState get initialState => FormTextFieldState.initState();
#override
Stream<FormTextFieldState> mapEventToState(FormTextFieldEvent event) async* {
if (event is TextChangedEvent) {
print("value received: ${event.eventText}");
yield FormTextFieldState(event.eventText);
}
}
}
import 'package:competitionapp/data_model/blocModels/formTextFieldBloc.dart';
import 'package:competitionapp/data_model/states/formTextFieldState.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
// ignore: must_be_immutable
class FormTextField extends StatelessWidget {
final TextEditingController _controller;
final String hint;
final IconData iconData;
final TextInputType inputType;
final int maxLines;
final int maxLength;
final EdgeInsetsGeometry padding;
final FormTextFieldBloc formTextFieldBloc;
FormTextField(this._controller, this.formTextFieldBloc,
{this.hint,
this.iconData,
this.inputType: TextInputType.text,
this.maxLines: 1,
this.maxLength,
this.padding: const EdgeInsets.fromLTRB(15, 5, 15, 5)});
#override
Widget build(BuildContext context) {
return Padding(
padding: padding,
child: BlocBuilder(
bloc: formTextFieldBloc,
builder: (context, FormTextFieldState state) {
if (state.text.isNotEmpty && state.text != null) {
_controller.text = state.text;
print("state text: ${state.text}");
}
return TextField(
onChanged: (value) {
print(value);
formTextFieldBloc.onChanged(_controller.text);
},
onEditingComplete: (){
print(_controller.text);
},
maxLength: maxLength ?? maxLength,
maxLines: maxLines,
keyboardType: inputType,
controller: _controller,
decoration: InputDecoration(
contentPadding: EdgeInsets.symmetric(vertical: 10),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.transparent, width: 0)),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.transparent, width: 0)),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.transparent, width: 0)),
hintText: hint,
hintStyle:
Theme.of(context).textTheme.caption.copyWith(fontSize: 18),
filled: true,
fillColor: Theme.of(context).cardColor,
prefixIcon: Icon(
iconData,
size: 16,
color: Theme.of(context).hintColor,
),
),
);
},
),
);
}
}
The issue here happens because the value on TextField is always overridden on _controller.text = state.text; and continuously updated on onChanged(). One way to approach this is to only update the TextField values when the entry is submitted i.e. on onFieldSubmitted()
You can check for a similar approach here. While it doesn't use a Stream to listen for changes, the TextField value needs to be updated with a desired format.