karvulf / flutter-reorderable-grid-view

BSD 3-Clause "New" or "Revised" License
155 stars 22 forks source link

ReactiveFormArray + ReorderableBuilder : Widget couldn't find a parent widget #100

Open Dionnie123 opened 1 year ago

Dionnie123 commented 1 year ago

demo

So I have this form that can containt list of reorderable sub-forms

The problem is, when I start to drag the items, it goes outside of the expected parent widget (ReactiveForm)

Error: ReactiveFormField widget couldn't find a parent widget. An instance of ReactiveTextField widget must be under a ReactiveForm or a ReactiveFormArray in the widgets tree.

Here is my code:

import 'package:digicard/app/models/custom_link.dart';
import 'package:digicard/ui/widgets/sliver_grid_delegate.dart';
import 'package:flutter/material.dart';
import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart';
import 'package:flutter_reorderable_grid_view/widgets/reorderable_builder.dart';
import 'package:reactive_forms/reactive_forms.dart';

class FieldsList extends StatefulWidget {
  final List<CustomLink> links;
  const FieldsList({super.key, required this.links});

  @override
  State<FieldsList> createState() => _LinksListState();
}

class _LinksListState extends State<FieldsList> {
  final _scrollController = ScrollController();
  final _gridViewKey = GlobalKey();
  final _fruits = List.generate(10, (index) => "TEST$index");

  @override
  Widget build(BuildContext context) {
    final form = ReactiveForm.of(context, listen: true) as FormGroup;
    return ReactiveFormArray(
        formArrayName: 'customLinks',
        builder: (context, array, child) {
          return Padding(
            padding: const EdgeInsets.all(8.0),
            child: Column(
              children: [
                ReorderableBuilder(
                  scrollController: _scrollController,
                  onReorder: (List<OrderUpdateEntity> orderUpdateEntities) {
                    for (final orderUpdateEntity in orderUpdateEntities) {
                      final fruit =
                          _fruits.removeAt(orderUpdateEntity.oldIndex);
                      _fruits.insert(orderUpdateEntity.newIndex, fruit);
                    }
                  },
                  builder: (children) {
                    return GridView(
                      padding: const EdgeInsets.all(12),
                      shrinkWrap: true,
                      key: _gridViewKey,
                      controller: _scrollController,
                      gridDelegate:
                          const SliverGridDelegateWithFixedCrossAxisCountAndFixedHeight(
                              crossAxisCount: 1,
                              crossAxisSpacing: 10,
                              mainAxisSpacing: 10,
                              height: 200),
                      children: children,
                    );
                  },
                  children: [
                    for (int i = 0; i < array.controls.length; i++)
                      Card(
                        key: Key(i.toString()),
                        shape: RoundedRectangleBorder(
                            side: BorderSide(
                                color: form.control("customLinks.$i").valid
                                    ? Colors.transparent
                                    : Colors.red,
                                width: 2.0),
                            borderRadius: BorderRadius.circular(8.0)),
                        child: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Column(
                            children: [
                              Row(
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceBetween,
                                children: [
                                  Wrap(
                                    children: [
                                      GestureDetector(
                                          child:
                                              const Icon(Icons.sort_rounded)),
                                      const SizedBox(
                                        width: 8.0,
                                      ),
                                      Text(widget.links[i].label)
                                    ],
                                  ),
                                  GestureDetector(
                                      child: const Icon(Icons.clear_rounded))
                                ],
                              ),
                              const SizedBox(height: 8),
                              ReactiveTextField(
                                formControlName: '$i.value',
                                decoration: InputDecoration(
                                  prefixIcon: widget.links[i].icon,
                                ),
                              ),
                              const SizedBox(height: 8),
                              ReactiveTextField(
                                formControlName: '$i.customLabel',
                                decoration: const InputDecoration(
                                    prefixIcon: SizedBox()),
                              ),
                            ],
                          ),
                        ),
                      ),
                  ],
                ),
              ],
            ),
          );
        });
  }
}
karvulf commented 1 year ago

Hello @Dionnie123 I can check this on the weekend, probably the Draggable widget is not working well with the package reactive_forms.