Home > Back-end >  2 textfields with the same value
2 textfields with the same value

Time:06-11

I have created a code that creates a text field when a button is pushed. i got the problem that if you type something in text field 1 it automaticly is in text field 2 so i cant have 2 diffrent things

I have the following code

int numberOfTextFields = 1;
  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          leading: CloseButton(),
          actions: buildEditingActions(),
          backgroundColor: Colors.red,
        ),
        body: SingleChildScrollView(
          padding: EdgeInsets.all(12),
          child: Form(
            key: _formKey,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                for(int i = 0 ; i < numberOfTextFields ; i  ) 
                buildExerciseComplete(),
                buildAddMore(),
              ],
            ),
          ),
        ),
      );

with is a simple button and the buildsets() being this:

Widget buildSets() => TextFormField(
        keyboardType: TextInputType.number,
        inputFormatters: <TextInputFormatter>[
          FilteringTextInputFormatter.digitsOnly
        ],
        style: TextStyle(fontSize: 15),
        decoration: InputDecoration(
          border: OutlineInputBorder(),
          labelText: 'Sets',
        ),
        onFieldSubmitted: (_) => saveForm,
        validator: (sets) =>
            sets != null && sets.isEmpty ? 'Sets cannot be empty' : null,
        controller: setsController,
      );

and this is the button:

Widget buildAddMore() => ElevatedButton(
            onPressed: () {
              setState((){
        numberOfTextFields  ;
    });
            },
            child: Text('Add new exercise'),  
          );
    

The way i store the information is in "sets" and if this was in like PHP i would say sets$numberOfTextFields to give them all a diffrent location to store. Im not quite sure how to do that in flutter and i tried the method with sets${numberOfTextFields}. but i dindt work

My code up here is a bit i a bit simplyfied. My real code looks like this: The problem is that the two diffrent fiels always have the same values Picture of how it looks

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'utils.dart';
import 'event_provider.dart';

class EventEditingPage extends StatefulWidget {
  final Event? event;

  const EventEditingPage({Key? key, this.event}) : super(key: key);

  @override
  _EventEditingPageState createState() => _EventEditingPageState();
}

class _EventEditingPageState extends State<EventEditingPage> {
  final _formKey = GlobalKey<FormState>();
  final setsController = TextEditingController();

  @override
  void initState() {
    super.initState();
      final event = widget.event!;

      setsController.text = event.Sets;
    }
  }

  @override
  void dispose() {
    setsController.dispose();
    super.dispose();
  }
  
int numberOfTextFields = 1;
  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          leading: CloseButton(),
          actions: buildEditingActions(),
          backgroundColor: Colors.red,
        ),
        body: SingleChildScrollView(
          padding: EdgeInsets.all(12),
          child: Form(
            key: _formKey,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                for(int i = 0 ; i < numberOfTextFields ; i  ) 
                buildExerciseComplete(),
                buildAddMore(),
              ],
            ),
          ),
        );
     

  List<Widget> buildEditingActions() => [
        ElevatedButton.icon(
          style: ElevatedButton.styleFrom(
              primary: Colors.transparent, shadowColor: Colors.transparent),
          onPressed: saveForm,
          icon: Icon(Icons.done),
          label: Text('Save'),
        )
      ];

 
  Widget buildExerciseComplete() => Container(
        padding: EdgeInsets.all(5.0),
        decoration: BoxDecoration(
          color: Color.fromARGB(255, 255, 200, 200),
          borderRadius: BorderRadius.circular(5.0),
          border: Border.all(
            width: 2.0,
          ),
        ),
        height: 50,
        child: Row(
          children: <Widget>[
            Expanded(
              child: Row(
                children: <Widget>[
                 Expanded(child: buildSets()),
                ],
              ),
            ),
          ],
        ),
      );

  Widget buildSets() => TextFormField(
        keyboardType: TextInputType.number,
        inputFormatters: <TextInputFormatter>[
          FilteringTextInputFormatter.digitsOnly
        ],
        style: TextStyle(fontSize: 15),
        decoration: InputDecoration(
          border: OutlineInputBorder(),
          labelText: 'Sets',
        ),
        onFieldSubmitted: (_) => saveForm,
        validator: (sets) =>
            sets != null && sets.isEmpty ? 'Sets cannot be empty' : null,
        controller: setsController,
      );

  
  Widget buildAddMore() => ElevatedButton(
            onPressed: () {
              setState((){
        numberOfTextFields  ;
    });
            },
            child: Text('Add new exercise'),  
          );
        
  

  


  Future saveForm() async {
    final isValid = _formKey.currentState!.validate();

    if (isValid) {
      final event = Event(
          Sets: setsController.text);

      
class Event {
  final String Sets;
  final Color backgroundColor;


  const Event({
    required this.Sets,
  });
}

CodePudding user response:

Setting the controller: setsController for every textfield in your loop is the cause of your issue, setting the same TextEditingController for multiple TextField will lead to have the same thing you type in all the textFields that shares the same controller, to solve this issue, you need to initialize a TextEditingController for every TextField


UPDATE:
To set a different controller for each field, you have to create a List<TextEditingController> and it must be the same size of your numberOfTextFields, pass the controller or the index to your method:

Widget buildSets(final TextEditingController controller) => TextFormField(
    keyboardType: TextInputType.number,
    inputFormatters: <TextInputFormatter>[
      FilteringTextInputFormatter.digitsOnly
    ],
    style: TextStyle(fontSize: 15),
    decoration: InputDecoration(
      border: OutlineInputBorder(),
      labelText: 'Sets',
    ),
    onFieldSubmitted: (_) => saveForm,
    validator: (sets) =>
        sets != null && sets.isEmpty ? 'Sets cannot be empty' : null,
    controller: controller,
  );
  //Calling the method:
  for(int i = 0 ; i < numberOfTextFields ; i  ) 
      buildSets(myControllers[i]),

CodePudding user response:

The problem is that you are using the same TextEditingController() with all the Text Fields, you have to create a controller for each one, you can do the following:

Step 1: Remove the currently used TextEditingController logic.

Step 2: In the screen containing the variable named numberOfTextFields, define a List of TextEditingController and start it with a controller inside:

List<TextEditingController> _textEditingControllers = [TextEditingController()];

Step 3: In add more function, when you increment the numberOfTextFields variable, add a new controller to the list:

onPressed: () {
    setState(() {
        numberOfTextFields  ;
        _textEditingControllers.add(TextEditingController());
    });
},

Step 4: Inside the loop when you create the Text Fields based on the value of the variable numberOfTextFields, pass the controller that corresponds the value of the loop counter i to the widget from the list:

children: [
    for(int i = 0 ; i < numberOfTextFields ; i   ) 
        buildExerciseComplete(controller: _textEditingControllers[i]),
        buildAddMore(),
],

*Note that the TextFormField is already nested in some widgets, then you have to pass the controller to the widget until you reach the TextFormField.

Step 5: In the screen where you declared the _textEditingControllers list, dispose all the controllers in the list in dispose method:

@override
void dispose() {
    for (TextEditingController controller in _textEditingControllers)
    {
        controller.dispose();
    }
    super.dispose();
}

That's It!

CodePudding user response:

Create separate respective controller for each field. You can use List<TextEditingController> controllers to store controllers in it and with each iteration of the loop, you can use controllers.add method to add a controller with controllers[i].text = '$i'. And set the controller in textField like this: controller: controllers['i'].

  • Related