1 year ago

#74488

test-img

Subtley_Wild

Flutter Bloc - Populate form fields based on selected dropdown item

I'm trying to use flutter bloc to allow a user select an employee name from a dropdown menu and then populate the form fields on the same screen based on the selected employee. These fields could then be edited. I have looked at the flutter todos example which is the closest functionality to what I want to do but its not exactly the same.

Currently I can get the dropdown button to show and select the employee object (JSON) but I cant get the form fields to populate based on this selection. I can access the employee object and its attributes via state but when I supply the variable to the initialValue attribute of a TextFormField it never shows anything even though printing the variable through the console shows its there.

I have been trying to do this with one bloc for the entire screen but I'm wondering now if its only possible to do this functionality with one bloc for the dropdown button and another bloc for the form.

I would Ideally like to stick with one bloc for the entire screen just for simplicity. Any ideas how I can populate the form fields based on the selected object from a dropdown using bloc state management

Heres some code:

@override
Widget build(BuildContext context) {
  return BlocListener<UpdateEmployeeBloc, UpdateEmployeeState>(
    listener: (context, state){
      if(state.status.isSubmissionFailure){
        ScaffoldMessenger.of(context)
          ..hideCurrentSnackBar()
          ..showSnackBar(const SnackBar(content: Text('Creation Failure')));
      }
    },
    child: Align(
      alignment: const Alignment(0, -1/3),
      child: ListView(
        scrollDirection: Axis.vertical,
        children: [
          const Padding(padding: EdgeInsets.only(top: 250)),
          Row(
            children: [
              Expanded(child: _SelectInput()),
            ],
          ),
          const Padding(padding: EdgeInsets.all(12)),

          Row(
            children: [
              Expanded(child: _FirstnameInput()),
              const Padding(padding: EdgeInsets.all(12)),
              Expanded(child: _LastnameInput()),
            ],
          ),
          const Padding(padding: EdgeInsets.all(12)),
          Row(
              children: [
                Expanded(child:_UsernameInput()),
                const Padding(padding: EdgeInsets.all(12)),
                Expanded(child:_PasswordInput()),
              ]
          ),
          const Padding(padding: EdgeInsets.all(12)),
          Row(
              children: [
                Expanded(child: _EmailInput()),
                const Padding(padding: EdgeInsets.all(12)),
                Expanded(child: _PhonenumberInput()),
              ]
          ),
          const Padding(padding: EdgeInsets.all(12)),
          Row(
              children: [
                Expanded(child: _JobTitleInput()),
                const Padding(padding: EdgeInsets.all(12)),
                Expanded(child: _RateInput()),
              ]
          ),
          const Padding(padding: EdgeInsets.all(20)),
          Container(
            padding: EdgeInsets.only(left: 100, right:100, ),
            child: _UpdateEmployeeButton(),
          )
        ],
      ),
    ),
  );
}
}


class _SelectInput extends StatelessWidget{
@override
Widget build(BuildContext context) {
  final employee_objects = context.select((UpdateEmployeeBloc bloc) => bloc.state.employees);
  EmployeeModel? selected_employee;

  //context.read<UpdateEmployeeBloc>().add(UpdateEmployeeFormLoaded());

  print("Employee Objects");

  return BlocBuilder<UpdateEmployeeBloc, UpdateEmployeeState>(
      buildWhen: (previous, current) => previous.employees != current.employees,
      builder: (context, state){
        return DropdownButton<EmployeeModel>(
          key: const Key('updateEmployeeForm_selectInput_textfield'),
          hint: Text("Choose an Employee"),
          value: selected_employee,
          items: employee_objects.map<DropdownMenuItem<EmployeeModel>>((EmployeeModel value){
            return DropdownMenuItem<EmployeeModel>(
              value: value,
              child: Text(value.fname + " " + value.lname),
            );
          }).toList(),
          onChanged: (newVal) {
            print("In onChanged method");
            selected_employee = newVal;
            //BlocProvider.of<UpdateEmployeeBloc>(context).add(EmployeeSelected(selected_employee!));
            context.read<UpdateEmployeeBloc>().add(EmployeeSelected(selected_employee!));
            print("After EmployeeSelected Event");
          },
          //style: Theme.of(context).textTheme.bodyText1,
        );
      }
  );
}
}



class _FirstnameInput extends StatelessWidget{
const _FirstnameInput({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
  String? employee = context.select((UpdateEmployeeBloc bloc) => bloc.state.employee?.fname);
  final state = context.watch<UpdateEmployeeBloc>().state;
  print("FirstnameInput has been built");
  print(state.employee?.fname);

  return BlocBuilder<UpdateEmployeeBloc, UpdateEmployeeState>(
      buildWhen: (previous, current) => previous.fname != current.fname,
      builder: (context, state){
        return TextFormField(
          key: const Key('createEmployeeForm_firstnameInput_textfield'),
          initialValue: employee,
          //initialValue: state.employee?.fname,
          style: Theme.of(context).textTheme.bodyText1,
          onChanged: (fname) => context.read<UpdateEmployeeBloc>().add(FirstnameChanged(fname)),
          decoration: InputDecoration(
            labelText: 'Firstname',
            errorText: state.fname.invalid ? 'Firstname is invalid' : null,
          ),
        );
      }
  );
}
}

Any help would be appreciated

json

flutter

dart

bloc

flutter-textformfield

0 Answers

Your Answer

Accepted video resources