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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions