Skip to content

Feature Request: Enhanced Support for Recursive Form Structures #200

@AhmedAlyDev

Description

@AhmedAlyDev

Description:

Hello! Thank you for the excellent work on reactive_forms_generator. I've found it incredibly valuable for most form scenarios, but I'm encountering significant limitations when working with recursive form structures.

The Problem: Recursive Form Models

Many real-world applications require forms with recursive relationships where a model contains instances of itself. Common examples include:

  • Survey/questionnaire builders (questions containing sub-questions)
  • Comment systems (comments with nested replies)
  • Organizational charts (employees managing other employees)
  • File systems (folders containing subfolders)
  • Rule engines (rules containing nested rules)

Current Limitation Example:

Consider this simple recursive model:

dart
class TreeNode {
  final String label;
  final List<TreeNode> children; // Recursive relationship
  
  TreeNode({required this.label, this.children = const []});
}

With the current generator, I cannot properly generate form structures for this model because:

  1. Infinite Recursion Risk: The generator cannot handle the circular dependency during code generation
  2. No Nested FormArray Support: There's no way to generate FormArray where each FormGroup represents another instance of the same recursive structure
  3. Missing Recursive Validation: Validation that needs to traverse the entire tree structure isn't supported

Current Workaround - Manual Implementation:

I'm forced to implement the entire form structure manually:

dart
// Manual form creation for recursive structure
FormGroup createTreeNodeForm(TreeNode? node) {
  return FormGroup({
    'label': FormControl<String>(value: node?.label, validators: [Validators.required]),
    'children': FormArray<Map<String, dynamic>>(
      node?.children.map((child) => createTreeNodeForm(child)).toList() ?? [],
      validators: [/* Complex recursive validation */]
    ),
  });
}

// Manual validator for recursive structure
class TreeNodeValidator extends Validator<dynamic> {
  @override
  Map<String, dynamic>? validate(AbstractControl<dynamic> control) {
    if (control is! FormGroup) return null;
    
    final errors = <String, dynamic>{};
    final labelControl = control.control('label');
    final childrenControl = control.control('children');
    
    // Validate current node
    if (labelControl.value == null) {
      errors['label'] = {'required': true};
    }
    
    // Recursively validate children
    if (childrenControl is FormArray) {
      final childrenErrors = <int, Map<String, dynamic>>{};
      for (int i = 0; i < childrenControl.controls.length; i++) {
        final childErrors = validate(childrenControl.controls[i]);
        if (childErrors != null) {
          childrenErrors[i] = childErrors;
        }
      }
      if (childrenErrors.isNotEmpty) {
        errors['children'] = childrenErrors;
      }
    }
    
    return errors.isEmpty ? null : errors;
  }
}

Requested Features:

  1. Recursive Model Annotation
    • A way to annotate recursive relationships to guide code generation
    • Example: @recursivefield() or @NestedForm() annotation
  2. Automatic FormArray Generation
    • Generate proper FormArray for recursive list fields
    • Handle the circular dependency during code generation
  3. Recursive Validation Support
    • Generate validators that can traverse recursive structures
    • Support for depth limits or other recursion constraints
  4. Helper Methods for Dynamic Operations
    • Generated methods for adding/removing nested recursive elements
    • Type-safe ways to manipulate the recursive form structure

Expected Usage:

dart
// Ideal future usage with enhanced generator support
@ReactiveForm()
class TreeNode {
  @ReactiveControl(validators: [RequiredValidator()])
  final String label;
  
  @RecursiveField() // New annotation for recursive relationships
  final List<TreeNode> children;
  
  TreeNode({required this.label, this.children = const []});
}

// Generated code would handle the recursive form creation and validation

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions