I have a problem with that field. This is the html "<form class="row" [formGroup]="fieldForm">
  <div class="col-12">
    <mat-form-field class="w-100">
      <mat-label>Generator</mat-label>
      <mat-select [formControl]="type">
        @for (generator of generatorTypes(); track generator) {
          <mat-option [value]="generator.value">{{
            generator.viewValue
          }}</mat-option>
        }
      </mat-select>
      <mat-hint>Choose how to generate values for this field</mat-hint>
    </mat-form-field>
  </div>

  @if (fieldForm.get("min")) {
    <div class="col-12">
      <mat-form-field class="w-100">
        <mat-label>Minimum Value</mat-label>
        <input matInput formControlName="min" placeholder="e.g., 1" />
        <mat-hint>Enter the minimum value of the range</mat-hint>
        <!-- <mat-error>{{ this.getErrorMessage("min") }}</mat-error> -->
      </mat-form-field>
    </div>
  }

  @if (fieldForm.get("max")) {
    <div class="col-12">
      <mat-form-field class="w-100">
        <mat-label>Maximum Value</mat-label>
        <input matInput formControlName="max" placeholder="e.g., 100" />
        <mat-hint>Enter the maximum value of the range</mat-hint>
      </mat-form-field>
    </div>
  }

  @if (fieldForm.get("values")) {
    <div class="col-12">
      <mat-form-field class="w-100">
        <mat-label>Values</mat-label>
        <input
          placeholder="e.g., 10, 20, 30"
          matInput
          formControlName="values"
        />
        <mat-hint>Enter numeric values separated by commas</mat-hint>
      </mat-form-field>
    </div>
  }

  @if (fieldForm.get("weights")) {
    <div class="col-12">
      <mat-form-field class="w-100">
        <mat-label>Weights</mat-label>
        <input
          [readonly]="autoRenew()"
          placeholder="e.g., 0.3, 0.3, 0.4"
          matInput
          formControlName="weights"
        />
        <mat-hint>
          Enter decimal weights between 0 and 1, separated by commas. The
          weights should sum to 1.
        </mat-hint>
        <button (click)="onToggleAutorenew()" matIconSuffix mat-icon-button>
          <mat-icon>{{ autoRenew() ? "autorenew" : "pause" }}</mat-icon>
        </button>
      </mat-form-field>
    </div>
  }

  @if (fieldForm.get("start")) {
    <div class="col-12">
      <mat-form-field class="w-100">
        <mat-label>Start</mat-label>
        <input placeholder="e.g., 0" matInput formControlName="start" />
        <mat-hint>Enter the starting value of the sequence</mat-hint>
      </mat-form-field>
    </div>
  }

  @if (fieldForm.get("step")) {
    <div class="col-12">
      <mat-form-field class="w-100">
        <mat-label>Step</mat-label>
        <input placeholder="e.g., 1" matInput formControlName="step" />
        <mat-hint
          >Enter the step size to increment or decrement the value</mat-hint
        >
      </mat-form-field>
    </div>
  }
</form>
" and this is the TS "import {
  ChangeDetectionStrategy,
  Component,
  DestroyRef,
  OnInit,
  inject,
  input,
  output,
  signal,
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import {
  FormControl,
  FormGroup,
  ReactiveFormsModule,
  Validators,
} from '@angular/forms';
import { startWith } from 'rxjs';
import { fieldGeneratorMap, GeneratorType } from '../schema-config.model';
import { compareToOtherFieldValidator } from '../../shared/validators/compare-to-other-field-validator.validator';
import { matchingArrayLengthsValidator } from '../../shared/validators/matching-array-lenghts-validator.validator';
import { numbersCommaSeparatedValidator } from '../../shared/validators/numbers-comma-separate-validator.validator';
import { SchemaFormFieldGeneratorService } from '../../shared/services/schema-form-field-generator.service';
import { TitleCasePipe } from '@angular/common';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatSelectModule } from '@angular/material/select';
import { RepeatMaskDirective } from '../../shared/directives/repeat-mask.directive';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';

type IntFieldGenerator =
  | { type: GeneratorType.Uniform; min: number; max: number }
  | { type: GeneratorType.Enum; values: number[]; weights: number[] }
  | { type: GeneratorType.NumericRange; start: number; step: number }
  | { type: GeneratorType.Values; values: number[] };

interface IntFieldForm {
  type: FormControl<GeneratorType>;
  min?: FormControl<number>;
  max?: FormControl<number>;
  values?: FormControl<string>;
  weights?: FormControl<string>;
  start?: FormControl<number>;
  step?: FormControl<number>;
}

@Component({
  selector: 'app-int-field',
  standalone: true,
  imports: [
    MatFormFieldModule,
    MatSelectModule,
    ReactiveFormsModule,
    MatInputModule,
    ReactiveFormsModule,
    TitleCasePipe,
    RepeatMaskDirective,
    MatButtonModule,
    MatIconModule,
  ],
  templateUrl: './int-field.component.html',
  styleUrl: './int-field.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class IntFieldComponent implements OnInit {
  private readonly schemaFormFieldGeneratorSvc = inject(
    SchemaFormFieldGeneratorService,
  );
  private readonly destroyRef = inject(DestroyRef);

  public readonly autoRenew = signal(true);

  public readonly generatorTypes =
    input.required<typeof fieldGeneratorMap.int_col>();
  public readonly changeField = output<IntFieldGenerator>();

  public readonly type = this.schemaFormFieldGeneratorSvc.getTypeField();
  public readonly min = this.schemaFormFieldGeneratorSvc.getMinField([
    Validators.min(-2147483648),
    compareToOtherFieldValidator(
      'max',
      (min: number, max: number) => min < max,
      'minGreaterThanMax',
    ),
  ]);
  public readonly max = this.schemaFormFieldGeneratorSvc.getMaxField([
    Validators.max(2147483648),
    compareToOtherFieldValidator(
      'min',
      (max: number, min: number) => min < max,
      'MaxSmallerThanMin',
    ),
  ]);
  public readonly values = this.schemaFormFieldGeneratorSvc.getValuesField([
    numbersCommaSeparatedValidator,
  ]);
  public readonly weights = this.schemaFormFieldGeneratorSvc.getWeightsField();
  public readonly start = this.schemaFormFieldGeneratorSvc.getStartField();
  public readonly step = this.schemaFormFieldGeneratorSvc.getStepField();
  public readonly fieldForm = new FormGroup<IntFieldForm>({
    type: this.type,
  });

  ngOnInit(): void {
    this.type.valueChanges
      .pipe(startWith(this.type.value), takeUntilDestroyed(this.destroyRef))
      .subscribe((type) => {
        this.updateFormControls(type);
      });

    this.fieldForm.valueChanges
      .pipe(
        startWith(this.fieldForm.value),
        takeUntilDestroyed(this.destroyRef),
      )
      .subscribe(() => {
        const schema = this.getTypedFormValue();
        if (schema) this.changeField.emit(schema);
      });

    this.min.valueChanges
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(() => {
        this.max.updateValueAndValidity({ emitEvent: false });
      });

    this.max.valueChanges
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(() => {
        this.min.updateValueAndValidity({ emitEvent: false });
      });

    this.values.valueChanges
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(() => {
        if (this.autoRenew() && this.values.valid) this.updateWeights();
      });

    this.weights.valueChanges
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(() => {
        this.values.updateValueAndValidity({ emitEvent: false });
      });
  }

  private updateFormControls(type: GeneratorType): void {
    switch (type) {
      case GeneratorType.Uniform:
        this.fieldForm.removeControl('values');
        this.fieldForm.removeControl('weights');
        this.fieldForm.removeControl('start');
        this.fieldForm.removeControl('step');

        this.fieldForm.addControl('min', this.min);
        this.fieldForm.addControl('max', this.max);

        break;

      case GeneratorType.Enum:
        this.fieldForm.removeControl('min');
        this.fieldForm.removeControl('max');
        this.fieldForm.removeControl('start');
        this.fieldForm.removeControl('step');

        this.fieldForm.addControl('values', this.values);
        this.fieldForm.addControl('weights', this.weights);

        this.updateValuesAndWeightsValidation();

        break;

      case GeneratorType.NumericRange:
        this.fieldForm.removeControl('min');
        this.fieldForm.removeControl('max');
        this.fieldForm.removeControl('values');
        this.fieldForm.removeControl('weights');

        this.fieldForm.addControl('start', this.start);
        this.fieldForm.addControl('step', this.step);
        break;

      case GeneratorType.Values:
        this.fieldForm.removeControl('min');
        this.fieldForm.removeControl('max');
        this.fieldForm.removeControl('weights');
        this.fieldForm.removeControl('start');
        this.fieldForm.removeControl('step');

        this.fieldForm.addControl('values', this.values);

        this.values.removeValidators(
          matchingArrayLengthsValidator(['weights']),
        );
        break;
    }
  }
  private getTypedFormValue(): IntFieldGenerator | undefined {
    const { type, min, max, values, weights, start, step } =
      this.fieldForm.value;

    switch (type) {
      case GeneratorType.Uniform:
        if (min && max) return { type, min: +min, max: +max };

        break;

      case GeneratorType.Enum:
        if (values && weights)
          return {
            type,
            values: values.split(',').map((v) => +v.trim()),
            weights: weights.split(',').map((v) => parseFloat(v)),
          };

        break;

      case GeneratorType.NumericRange:
        if (start && step)
          return {
            type,
            start: +start,
            step: +step,
          };

        break;

      case GeneratorType.Values:
        if (values)
          return {
            type,
            values: values.split(',').map((v) => +v.trim()),
          };

        break;
    }

    return undefined;
  }

  private calculateWeights(values: string): string {
    const valueArray = values
      .split(',')
      .map((v) => v.trim())
      .filter((v) => v !== '');

    if (valueArray.length === 0) return '';

    const weight = (1 / valueArray.length).toFixed(2);

    return Array(valueArray.length).fill(weight).join(', ');
  }

  private updateValuesAndWeightsValidation(): void {
    if (this.autoRenew()) {
      this.values.removeValidators(matchingArrayLengthsValidator(['weights']));
      this.weights.removeValidators(matchingArrayLengthsValidator(['values']));
    } else {
      this.values.addValidators(matchingArrayLengthsValidator(['weights']));
      this.weights.addValidators(matchingArrayLengthsValidator(['values']));
    }

    this.values.updateValueAndValidity({ emitEvent: false });
    this.weights.updateValueAndValidity({ emitEvent: false });
  }

  private updateWeights(): void {
    const calculatedWeights = this.calculateWeights(this.values.value || '');
    this.weights.setValue(calculatedWeights, { emitEvent: true });
  }

  public onToggleAutorenew(): void {
    this.autoRenew.update((value) => !value);

    this.updateValuesAndWeightsValidation();

    if (this.autoRenew()) this.updateWeights();
  }

  public getErrorMessage(controlName: string): string {
    const control = this.fieldForm.get(controlName);

    if (control && control.invalid && (control.touched || control.dirty)) {
      const errors = control.errors;
      if (errors) {
        const errorMessages: { [key: string]: string } = {
          required: 'This field is required',
          min: `Minimum value is ${errors['min'].min}`,
          max: `Maximum value is ${errors['max'].max}`,
          minGreaterThanMax: 'Minimum value should be less than maximum value',
          MaxSmallerThanMin:
            'Maximum value should be greater than minimum value',
          numbersCommaSeparated: 'Please enter valid comma-separated numbers',
          matchingArrayLengths: 'The number of values and weights should match',
        };

        const firstErrorKey = Object.keys(errors)[0];
        return errorMessages[firstErrorKey] || 'Invalid input';
      }
    }

    return '';
  }
}
". The problem it's that i need a way to make that method reactive so that i can display errors based on each formControl. Also another problem it's that i have also 20+ fields like that, so it's not a good idea to copy that method to each one of them. We need something like a service but idk. what do you suggest?