Flutter, how to dispose textController - flutter

I'm learning Flutter and I have in my app, two textFields linked to textControllers in an AlertDialog to get the input from a user as text and display it in cards in the body of the screen. My problem, that I can't solve on my own, is that after I added setState(() {}) in the 'Save' button of the AlertDialog, for the text to acutally get displayed on the screen in body, well after this change the text entered in the TextFields doesn't get cleared aymore after pressing 'Save'.
My Code:
class _HomeScreenState extends State<HomeScreen> {
final TextEditingController titleController = TextEditingController();
final TextEditingController textController = TextEditingController();
DummyDataProvider notes;
#override
void dispose() {
// Clean up the controller when the widget is disposed.
titleController.dispose();
textController.dispose();
super.dispose();
}
The textControllers in question:
MaterialButton(
onPressed: () {
setState(() {
final title = titleController.text;
final text = textController.text;
NoteProvider.insertNote({'title': title, 'text': text});
Navigator.pop(context);
});
What i mean by text not disposing:
https://imgur.com/a/8pyTPM7,
https://imgur.com/a/lr8a3Eh
Thank you in advance!

Why not just use clear()?
final _textController = TextEditingController();
.....
.....
onPressed: () {
_textController.clear();
}

You can reset your text controllers.
For example in onpressed:
titleController = new TextEditingController();
textController = new TextEditingController();
Set state is not required for this.

TextEditingController
Is very expensive object, don't create it often
just use
TextEditingController.text == '';
to clear the text,

Related

Edit form in flutter with getx

im new for both flutter and getx and i'm trying to make edit Form with getx , but i get Null .. how to fill TextEditingController after api response
class EditMarketerController extends GetxController {
final DashboardApiProvider dashboardApiProvider;
EditMarketerController({required this.dashboardApiProvider});
MarketerToEdit marketer = MarketerToEdit();
TextEditingController usernameController =
TextEditingController();
TextEditingController emailController =
TextEditingController();
#override
void onInit() {
_getMarketer(); //----- **api call**
// Wait until the completion of the data call and then fill ↓↓↓
final usernameController = TextEditingController(text:
marketer.username);
final emailController = TextEditingController(text:
marketer.email);
super.onInit();
}
Use callBack in your _getMarketer method like this.
_getMarketer({Function? callBack}){
/// implement your api and put callBack in your api call success like this
if(callBack != null){
callBack();
}
}

Flutter TextEditingController.txt not updating on first build

I am trying to clean up my code a lot. I have a form that I realise I use multiple times in my app. So I wanted to turn the form into its own stateful widget so I could easily re-use it. Unfortunately this is proving more difficult than I thought.
The form is first used in the app to add items. I then want to re-use that same form to edit items and change values in those text fields.
I call the new widget that I created:
body: const GearForm(
onSaveFunctionType: 'add',
itemID: 'none',
itemManufacturer: 'hi',
itemName: '',
itemType: 'test',
itemVolume: '',
itemWeight: '',
packCategory: '',
tempRating: '',
),
If I am passing arguments into the widget though they do not show up in the form when I am testing:
class GearForm extends StatefulWidget {
const GearForm(
{Key? key,
required this.onSaveFunctionType,
required this.itemID,
required this.itemName,
required this.itemManufacturer,
required this.itemType,
required this.packCategory,
required this.itemWeight,
required this.tempRating,
required this.itemVolume})
: super(key: key);
final String onSaveFunctionType;
final String itemID;
final String itemName;
final String itemManufacturer;
final String itemType;
final String packCategory;
final String itemWeight;
final String tempRating;
final String itemVolume;
#override
State<GearForm> createState() => _GearFormState();
}
//define category stream stream
Stream<DocumentSnapshot<Map<String, dynamic>>> streamUserCategories() {
FirebaseFirestore db = FirebaseFirestore.instance;
String userID = FirebaseAuth.instance.currentUser!.uid;
return db.collection('UserPackCategoryList').doc(userID).snapshots();
}
class _GearFormState extends State<GearForm> {
FirebaseAnalytics analytics = FirebaseAnalytics.instance;
FirebaseFirestore db = FirebaseFirestore.instance;
String userID = FirebaseAuth.instance.currentUser!.uid;
//text editing controllers
TextEditingController itemNameController = TextEditingController();
TextEditingController manufacturerController = TextEditingController();
TextEditingController itemTypeController = TextEditingController();
TextEditingController packCategoryController = TextEditingController();
TextEditingController itemWeightController = TextEditingController();
TextEditingController temperatureRatingController = TextEditingController();
TextEditingController volumeController = TextEditingController();
#override
Widget build(BuildContext context) {
//get entitlements from revenue cat
final Entitlement entitlement =
Provider.of<RevenueCatProvider>(context).entitlement;
print(widget.itemManufacturer);
//set initial controller values
itemNameController.text = widget.itemName;
manufacturerController.text = widget.itemManufacturer;
itemTypeController.text = widget.itemType;
packCategoryController.text = widget.packCategory;
itemWeightController.text = widget.itemWeight;
temperatureRatingController.text = widget.tempRating;
volumeController.text = widget.itemVolume;
The odd part is if I did a cmd+s in visual studio code then all the value would magically appear. Since the Cmd+s worked I thought it was showing the values on rebuild so I tried wrappign everythign in setState:
#override
Widget build(BuildContext context) {
//get entitlements from revenue cat
final Entitlement entitlement =
Provider.of<RevenueCatProvider>(context).entitlement;
print(widget.itemManufacturer);
setState(() {
//set initial controller values
itemNameController.text = widget.itemName;
manufacturerController.text = widget.itemManufacturer;
itemTypeController.text = widget.itemType;
packCategoryController.text = widget.packCategory;
itemWeightController.text = widget.itemWeight;
temperatureRatingController.text = widget.tempRating;
volumeController.text = widget.itemVolume;
});
but that didnt fix the issue either...
Update:
I did soem further troubleshooting and tried initState:
#override
void initState() {
super.initState();
print(widget.itemManufacturer);
itemNameController.text = widget.itemName;
manufacturerController.text = widget.itemManufacturer;
itemTypeController.text = widget.itemType;
packCategoryController.text = widget.packCategory;
itemWeightController.text = widget.itemWeight;
temperatureRatingController.text = widget.tempRating;
volumeController.text = widget.itemVolume;
//set initial controller values
}
What is super odd here is that my print(widget.itemManufacturer); works fine and I see the correct value. But it is not being assigned to the manufacturerController.text = widget.itemManufacturer; a few lines down.
Use initState or you can use late
late TextEditingController itemNameController =
TextEditingController.fromValue(TextEditingValue(text: widget.itemName));
The reason why the value were not showing in my form fields was because I am using autocomplete. Autocomplete upon further research has an initial Value field:
initialValue: TextEditingValue(text: manufacturerController.text),
Once I used that initalValue field all updated accordingly.

How to save value from TextField in Flutter to use it in other places

i am creating very easy app - user will get 4 texfields and he will put there numbers. Then i want to do some math on that numbers.
How is it possible to save that inputs in variables which i could use wherever i want and in relevant moment?
For now i only created possibility to display it on this class where they were created:
my TextFields look like this (i have 4 textfields: e, f, g and h:
var e = '';
TextField(
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
onChanged: (newVal) {
e = newVal;},),
And this is button - when i click it i can see inputs
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text('You wrote $d $e $f $g'),
);
},
);
But how to save that inputs to variables outside this class?
You can save the value from onChanged to a state management solution like StatefulWidget or Providers and so on.
TextField(
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
onChanged: (newVal) {
if(newVal != null){
context.read<SignUpBloc>().add(SignUpEvent.mobileChanged(mobile: newVal));
}
},),
This is how we do it in Bloc. You can do the same in any other state management solution or even store it locally in SharedPreferences as well.
First you need to create a TextEditingController inside you class for each field you want to change:
class _MyClassWithDataState extends State<MyClassWithData> {
TextEditingController textController1 = TextEditingController();
TextEditingController textController2 = TextEditingController();
TextEditingController textController3 = TextEditingController();
TextEditingController textController4 = TextEditingController();
}
and define on the other class the data you will need:
class ClassWithReceivedData extends StatefulWidget {
const ClassWithReceivedData({
Key? key,
required this.text1,
required this.text2,
required this.text3,
required this.text4,
}) : super(key: key);
final TextEditingController text1;
final TextEditingController text2;
final TextEditingController text3;
final TextEditingController text4;
#override
State<ClassWithReceivedData> createState() =>
_ClassWithReceivedDataState();
}
then when you navigate to other page you simple pass:
Navigator.push(context, new MaterialPageRoute(builder: (context) => new
ClassWithReceivedData(text1: textController1, text2: textController2,
text3: textController3, text4: textController4);
but if you really need to retrieve data on multiple classes i suggest to create a Controller or a Store class for the data you need an then use an state managment like Provider, Get, Mobx, etc..., to retrieve data whatever you want.

Flutter Firestore Automatically create new Document when editing Field

I am pulling data from Firestore and Editing, and when I click on the data to edit, I don't see it showing anything, however when I write the information and Save. Instead of changing the Edited Field, I get a new document with the edited field.
For example in the code, I edit the name => I will have a new document with the email reused and name changed.
And here is my code:
class EditHouse extends StatefulWidget {
final House house;
EditHouse(this.house);
class _EditHouseState extends State<EditHouse> {
final nameController = TextEditingController();
final emailController = TextEditingController();
#override
void dispose() {
nameController.dispose();
emailController.dispose();
super.dispose();
}
#override
void initState() {
if (widget.house == null) {
nameController.text == "";
emailController.text == "";
new Future.delayed(Duration.zero, () {
final houseProvider =
Provider.of<HouseProvider>(context, listen: false);
houseProvider.loadValues(House(
name: '',
email: ''));
});
} else {
nameController.text = widget.house.name;
emailController.text = widget.house.email;
new Future.delayed(Duration.zero, () {
final houseProvider =
Provider.of<HouseProvider>(context, listen: false);
houseProvider.loadValues(widget.house);
});
}
super.initState();
}}
I don't know if the problem lies here or not EditHouse(this.house);
when I can't use it EditHouse([required this.house]); I will get an error message Can't have modifier 'required' here

Clear TextField without controller in Flutter

My screen has multiple textfields, about 15 or so. I don't want to use TextEditingController due to performance reasons as the number of TextFields are likely to grow and I need to pass data from one widget to another back and forth. So I am using OnChanged method of the TextField and am setting a variable which will be used from the parent widget through a function. Now when I click on reset on the parent widget, how do I clear all the values in the TextField controls without using TextEditingController?
class Parent extends StatelessWidget {
String txt='';
myfunction(text)
{
txt=text;
}
#override
Widget build(BuildContext context) {
...
Foo(myfunction);
....
}
}
class Foo extends StatelessWidget {
final Function myfunction;
const Foo(this.myfunction);
#override
Widget build(BuildContext context) {
return TextField(
onChanged: (text) {
myfunction( text);
},...
}
}
You should try to declare all textfields with:
final TextEditingController name = TextEditingController();
final TextEditingController age = TextEditingController();
Create one method like this :
resetAll() {
name.clear();
name.clear();
}
then you call resetAll on reset button like below:
onPressed:() => resetAll()
It's not possible, but the text Fields will be reset if you dispose and reopen the screen holding the text Fields.