This is a migrated thread and some comments may be shown as answers.
Preferred Way to Validate When Using ValueNormalizer?
7 Answers 13 Views
This is a migrated thread and some comments may be shown as answers.
Keith
Top achievements
Rank 1
Keith asked on 20 Feb 2021, 11:32 PM

I am using kendo FormFields and I have a combobox using the ValueNormalizer in the html.  It also has a validator in the ts for maxlength.  I notice that the ValueNomalizer function still fires even when the maxlength is exceeded.  I can see a brief red line around the textbox area before it fires off and returns from my service.  In 

Here are a few code snippets:

<kendo-formfield>
  <kendo-label [for]="'kn'" text="Product"></kendo-label>
  <kendo-combobox
    [formControlName]="'kn'"
    [data]="listItems"
    [textField]="'ProductName'"
    [valueField]="'ProductID'"
    [valueNormalizer]="valueNormalizer"
    [allowCustom]="true"
    [suggest]="true"
  >
  </kendo-combobox>
  <kendo-formhint>Select or type product</kendo-formhint>
  <kendo-formerror>
    Ooops!
    <div *ngIf="form.get('kn').errors && form.get('kn').errors.required">
      Required
    </div>
      <div *ngIf="form.get('kn').errors && form.get('kn').hasError('maxlength')">
      too big!
    </div>
  </kendo-formerror>
</kendo-formfield>

........

export class AppComponent implements OnInit {
  public form: FormGroup = new FormGroup({
    kn: new FormControl(null,
    [
      Validators.required,
    alidators.maxLength(5)
    ]),
  });

......

public valueNormalizer = (text: Observable<string>): any =>
  text.pipe(switchMap(this.service));

.......

public service = (text: string): any => {
  console.log(text);
  let a = this.http.post("normalize/url", { text });
  console.log("The A:");
  console.log(a);
  return a;
};

 

Here is a StackBlitz: https://stackblitz.com/edit/valuenormalizerandvalidation?file=app/app.component.ts

What do I need to do in order for the valueNormalizer to not be called if the if the form is not valid?  I'd like the error to be displayed.  I've tried breaking out the valueNormalizer function from using lambda notation, but then I don't have access to 'this.service' scope.

Best wishes,
Keith Nicholson

7 Answers, 1 is accepted

Sort by
0
Missing User
answered on 23 Feb 2021, 03:01 PM

Hello Keith,

Thank you for the provided snippets and especially for the runnable example. Makes it much easier to identify the problem quickly.

The valueNormalizer will be called each time the ComboBox tries to resolve the typed text as component value. When a custom string is typed into the input, an attempt to resolve the value occurs on enter press or on component blur. There is no way to stop that. Even if you pass a valueNormalizer only conditionally, that would result in a JavaScript error, when the component tries to resolve a value and no normalizer is present.

An option is to reject and clear the value if the typed text is too long, but that's not what you are after if I understand your requirements correctly.

One more suitable approach is to accept the value but mark the control as invalid after the valueNormalizer completes. In the code snippets, you've used Validators.maxLength(5) - that won't work on the selected ComboBox value, as it is actually an object and not a string that you can check and validate the length of. To get around this, you can build your own validator that checks the length of a targeted property value:

export function maxLenghtValidator(maxLength: number, propName: string): ValidatorFn { return (control: AbstractControl): { [key: string]: any } | null => { const value = control.value ? control.value[propName] : null;

return !value || value.length <= maxLength ? null : { maxlength: { value: control.value } }; }; }

Here's a StackBlitz example demonstrating the suggested approach. After you type a long value and press enter, the valueNormalizer processes the value and once it's resolved as component value, the validator kicks in and invalidates the control.

As a side note, there's an open feature request about adding a maxlength property to the ComboBox. That's not exactly the same as what you've requested, but could still be useful may be in your scenario as well. I'd encourage you to vote for this feature if that's the case. Alternatively, you can submit your own feature request, where you describe the exact expectations for a possible new feature, if you'd like. Some of the requests on our Feedback portal make their way to our roadmap, if they prove to be popular enough.

Let me know if I could provide more information on the topic.

Regards,
Dimitar
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Keith
Top achievements
Rank 1
answered on 25 Feb 2021, 07:33 PM
Dimitar,

Thanks for the reply.  I'm going through it now and will follow-up with additional thoughts or close this out today/tomorrow.
0
Missing User
answered on 26 Feb 2021, 07:54 AM

Hello Keith,

Take your time and let me know how it goes. The ticket will remain open and the status can anyway always be changed.

Regards,
Dimitar
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Keith
Top achievements
Rank 1
answered on 03 Mar 2021, 07:22 PM

Hi Dimitar!

I have been looking through this and I have implemented it into my real solution and seems to work well.  Thank you!

Can you recommend how to unit test this?  I'm not sure how to set the Form Control to have the propName as part of the setup.

Peace,
Keith

0
Ivan
Telerik team
answered on 05 Mar 2021, 02:56 PM

Hi Keith,

If I understood you correctly I would recommend an end-to-end test for verifying the requirement. It will help with properly testing the desired behavior and it will be far easier to implement properly. 

Another option is that you could use our tests for examples and more information on the topic of all testing as all of the kendo components and their parts are heavily tested with both unit tests and e2e tests on our side. Most of our unit tests and e2e tests can be found in the source code of the components and here is how you can access it https://www.telerik.com/kendo-angular-ui/components/installation/source-code/ There are multiple tests for the valueNormalizer there and a lot more for the combobox itself.

Let me know if the e2e approach is applicable in your case or if I could provide you with more information

Regards,
Ivan
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

0
Keith
Top achievements
Rank 1
answered on 05 Mar 2021, 06:02 PM
Ivan,

I'll look into the referenced unit tests with the source code and get back.  Thank you.
0
Martin
Telerik team
answered on 09 Mar 2021, 07:41 AM

Hi Keith,

Sure. Take your time.

If you have any further questions, do not hesitate to write back here. Keep in mind that all tickets are automatically closed after 2 weeks of inactivity. However, you can open it whenever you want.

Regards,
Martin
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Asked by
Keith
Top achievements
Rank 1
Answers by
Missing User
Keith
Top achievements
Rank 1
Ivan
Telerik team
Martin
Telerik team
Share this question
or