Issue with kendo-formfield in Customized FormFieldComponent: "The kendo-formfield component should contain only one control" Error

2 Answers 133 Views
FormField Forms
Layth
Top achievements
Rank 1
Iron
Layth asked on 25 Nov 2024, 04:25 PM
Hello Team

I’m encountering an issue with the kendo-formfield component when used within my custom wrapper component, FormFieldComponent. Even though I am passing a single form control with formControlName, the component keeps throwing the following error:


Error: The `kendo-formfield` component should contain only one control of type NgControl with a formControlName or an ngModel binding.

My Setup:

I’ve created a custom wrapper component, FormFieldComponent, which looks like this:

import { Component, Input, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { InputsModule, Orientation, ShowOptions } from '@progress/kendo-angular-inputs';

@Component({
  selector: 'mnp-form-field',
  standalone: true,
  imports: [CommonModule, InputsModule],
  encapsulation: ViewEncapsulation.None,
  template: `
    <kendo-formfield [orientation]="orientation!" [showErrors]="showErrors!" [showHints]="showHints!">
      <ng-content></ng-content>
    </kendo-formfield>
  `,
  styleUrl: './form-field.component.scss',
})
export class FormFieldComponent {
  @Input() orientation?: Orientation;
  @Input() showErrors?: ShowOptions;
  @Input() showHints?: ShowOptions;
}
In my Storybook story, I’m using this component with a ReactiveFormsModule setup. Here’s the story code:


export const EmailFieldWithFormGroup: Story = {
  render: () => {
    const formBuilder = new FormBuilder();

    const emailForm: FormGroup = formBuilder.group({
      email: ['', [Validators.required, Validators.email]],
    });

    return {
      props: {
        emailForm,
        emailControl: emailForm.get('email'),
        onSubmit: () => {
          if (emailForm.valid) {
            console.log('Form submitted:', emailForm.value);
          } else {
            console.error('Form is invalid');
          }
        },
      },
      template: `
        <form [formGroup]="emailForm" (ngSubmit)="onSubmit()">
          <fieldset>
            <legend>Email Field</legend>
            <mnp-form-field>
              <mnp-label [for]="'email'" text="Email"></mnp-label>
              <mnp-textbox formControlName="email"></mnp-textbox>
              <mnp-form-hint>Enter your email address</mnp-form-hint>
              <mnp-form-error *ngIf="emailForm.controls['email'].invalid && emailForm.controls['email'].touched">
                Error: Please provide a valid email address.
              </mnp-form-error>
            </mnp-form-field>
          </fieldset>
        </form>
      `,
    };
  },
};


2 Answers, 1 is accepted

Sort by
0
Zornitsa
Telerik team
answered on 28 Nov 2024, 12:42 PM

Hi Layth,

Thank you for the details and code snippets provided.

Based on the shared information provided, I implemented a similar scenario to the explained one in the following StackBlitz example and indeed noticed the same error message appearing once trying to wrap the FormFieldComponent in a custom component:

To better explain the reason behind this behavior, the FormFieldComponent cannot be wrapped in another custom component, because in the current scenario, the FormFieldComponent is not recreated but is reused. This means that only its internal content is being changed, which makes it seem like there are multiple form controls inside it.

However, the default behavior of the FormFieldComponent implies that only a single form component should be rendered inside and thus the experienced error emerges in the console given such an implementation.

With the above being said, an alternative approach that might prove to be useful in the specific scenario would be for the developer to wrap the FormFieldComponent together with the desired form controls and conditionally render the desired form control depending on the certain condition. For example:

<kendo-formfield [showHints]="showHints" [showErrors]="showErrors">
    <kendo-textbox *ngIf="typeControl === 'textbox'" [formControl]="control"></kendo-textbox>
    <kendo-datepicker *ngIf="typeControl === 'datepicker'" [formControl]="control" required>. 
    </kendo-datepicker>
    <kendo-formhint>{{hintMessage}}</kendo-formhint>
    <kendo-formerror>{{errorMessage}}</kendo-formerror>
</kendo-formfield>

Here is also the above-linked StackBlitz example, updated to showcase the proposed suggestion, in which no error can be observed:

It is important to mention that the demo aims to point the developer in the right direction and any additional modifications required to fully fit the specific use case are considered the developer's effort.

I hope the provided information sheds some light on the matter. 

Regards,
Zornitsa
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Layth
Top achievements
Rank 1
Iron
commented on 28 Nov 2024, 04:19 PM | edited


Hi Zornitsa;
Thank you for the detailed explanation and example provided in response to my query about using the kendo-formfield within a custom wrapper component. The solution provided suggests a method for conditionally rendering controls based on specific conditions, which is useful. However, I am facing a scenario where I need to handle multiple validation errors dynamically within the same form field.

Could you please provide guidance or an example on how I might implement a setup where multiple error messages can be dynamically displayed for a single form control within the kendo-formfield? Specifically, I am looking for a way to display different error messages based on various validation failures without having to create a separate template or component for each error scenario.

Is there a recommended approach to managing and displaying these validations dynamically within the kendo-formfield using Angular's reactive forms?

Thank you for your assistance.

Best regards,
Layth Alshareefi

0
Zornitsa
Telerik team
answered on 03 Dec 2024, 09:01 AM

Hi Layth,

Thank you for the further clarifications provided.

Given the suggested approach in my previous reply on how to implement a wrapper for the FormFieldComponent, the developer can conditionally display error messages for the separate form controls by checking the type of the current form control and rendering the desired error messages depending on the particular validation rules defined for this form control. For example:

<kendo-formfield [showHints]="showHints" [showErrors]="showErrors">
        <kendo-textbox *ngIf="typeControl === 'textbox'" [formControl]="control" required></kendo-textbox>
        <kendo-datepicker *ngIf="typeControl === 'datepicker'" [formControl]="control" required></kendo-datepicker>
        <kendo-formhint>{{hintMessage}}</kendo-formhint>
        <kendo-formerror *ngIf="typeControl === 'textbox'">
          <span *ngIf="control.errors?.required">
            Error: Username is required
          </span>
          <span *ngIf="control.errors?.minlength">
            Error: Username has to be at least 3 characters
          </span>
          <span *ngIf="control.errors?.maxlength">
            Error: Username has to be less than 12 characters
          </span>
        </kendo-formerror>
        <kendo-formerror *ngIf="typeControl === 'datepicker'">
          <span *ngIf="control.errors?.required">
            Error: Birthday is required
          </span>
        </kendo-formerror>
</kendo-formfield>

To better illustrate the results from the proposed suggestion, please refer to the following StackBlitz example:

In the above demo, it can be observed how a different error message is displayed depending on the current validation rule that is not fulfilled.

Please observe the provided information and let me know how it works for your scenario.

Regards,
Zornitsa
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Tags
FormField Forms
Asked by
Layth
Top achievements
Rank 1
Iron
Answers by
Zornitsa
Telerik team
Share this question
or