Error with validation(Angular)

Hello,

For my current use case I needed to build custom renderers using bootstrap UI. I’ve basically built off of the angular/materialRenderers but have changed the UI aspect and tweaked some parts for my needs. For example, here Is my textRenderer:

import { ChangeDetectionStrategy, Component } from '@angular/core';
import { FormControl } from '@angular/forms';
import { JsonFormsAngularService, JsonFormsControl } from '@jsonforms/angular';
import { Actions, and, isDateControl, isEnumControl, isStringControl, or, Tester } from '@jsonforms/core';
import { forEach } from 'lodash';


@Component({
  selector: 'TextControlRenderer',
  template: `
    <div class="mb-2" [hidden]="hidden" [ngStyle]="{'width': '60%'}" *ngIf="getType()==='radio'">
    <label>{{label}}</label>
    <div class="form-check" *ngFor="let enum of this.enumArray">
    <input
    [id]="id"
    [formControl] ="form"
    type="checkbox"
    (change)="onChange($event)"
    class="form-check-input mt-1">
    <label class="form-check-label">{{enum}}</label>
    <!--     <span *ngIf="shouldShowUnfocusedDescription()">{{description}}</span> -->
     <span class="description">{{description}}</span>
     <span class="error-msg">{{error}}</span>
     </div>
    </div>


  <div class= "mb-2" [hidden]="hidden" *ngIf="getType()==='date'">
    <label class="form-control-label inline-block">{{label}}</label>
    <input
    [ngStyle]="{'width': '17%'}"
    [id]="id"
    [formControl] ="form"
    type="date"
    class="form-control"
    (change)="onChange($event)">
        <!--<span *ngIf="shouldShowUnfocusedDescription()">{{description}}</span> -->
     <span class="description">{{description}}</span>
     <span class="error-msg">{{error}}</span>
</div>

  <div class= "mb-2" [hidden]="hidden" [ngStyle]="{'width': '60%'}" *ngIf="getType()==='text'">
    <label class="form-control-label inline-block">{{label}}</label>
    <input
    class="form-control"
    type="text"
    (input) ="onChange($event)"
    [id] = "id"
    [formControl] ="form"
    [maxlength]="getMaxLength()"
    >
        <!--     <span *ngIf="shouldShowUnfocusedDescription()">{{description}}</span> -->
    <span class="description"> {{description}}</span>
    <span class="error-msg" *ngIf="form.invalid">{{error}}</span>
  </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class TextControlRenderer extends JsonFormsControl {
  constructor(jsonformsService: JsonFormsAngularService) {
    super(jsonformsService);
    console.log('construct');

  }
  enumArray : any[] = [];

  getEventValue = (event: any) => event.target.value;
  getType = (): string => {
    if (this.uischema.options && this.uischema.options.format) {
      this.enumArray = this.scopedSchema.enum as any[];
      return this.uischema.options.format;

    }
    if (this.scopedSchema && this.scopedSchema.format) {
      switch (this.scopedSchema.format) {
        case 'email':
          console.log('email');
          return 'email';
        case 'tel':
          console.log('tel');
          return 'tel';
          case 'date':
            console.log('date');
            return 'date'
        default:
          console.log('text1');
          return 'text';
      }
    }
    return 'text';
  };

  getMaxLength() : number{
  if(this.scopedSchema.maxLength !== undefined){
     return this.scopedSchema.maxLength;
   }
   return -1;
  }

  updateCore(){
    this.updateCore();
  }


}
export const BootstrapTextControlRendererTester: Tester = and(
  isStringControl
// or(  isDateControl, isEnumControl)
);

I’ve registered it in the renderers array:

 renderers = [
    { tester: rankWith(3, BootstrapTextControlRendererTester), renderer: TextControlRenderer},
    { tester: rankWith(3, BoostrapNumberControlTester), renderer: NumberControlRenderer},
    { tester: rankWith(3, BootstrapTextAreaRendererTester), renderer: TextAreaRenderer},
   ...angularMaterialRenderers,
  ];```
Here is my jsonform root:

<jsonforms
#form
[uischema]=“uiSchema”
[schema]=“schema”
[renderers]=“renderers”
[ajv] = “ajv”
[locale]=“‘de-DE’”
[(data)]=“formData”
(dataChange)=“onChange($event)”
validationMode=“ValidateAndShow”
(errors)=“errorz($event)”

``` Here is my ajv instance:
ajv = createAjv({
    schemaId: 'auto',
    allErrors: true,
    jsonPointers: true,
    errorDataPath: 'property'
  });

I keep getting this error:

core.js:6210 ERROR TypeError: validator is not a function
    at validate (core.js:37:1)
    at Object.push.py/A.exports.sanitizeErrors (core.js:47:1)
    at Object.push.py/A.exports.coreReducer (core.js:176:1)
    at JsonFormsAngularService.push.DAox.JsonFormsAngularService.updateCore (jsonforms.service.js:103:1)
    at TextControlRenderer.onChange (textRenderer.ts:74:27)
    at TextControlRenderer_div_2_Template_input_input_3_listener (textRenderer.ts:47:5)
    at executeListenerWithErrorHandling (core.js:15279:1)

This is happening for all my custom controls, and is also happening when I unregister my controls in the renderer and use the default material renderers. However when I change validationMode = “noValidation” on my jsonform root it works as expected. So there is some error happening when trying to validate my formcontrols.
Thanks for your time

Hi @Jayrack813,

The validator is the function which is generated by Ajv when its compile method is called. Something is going wrong here with the custom AJV instance. The reason noValidation “works” is because then AJV is completely ignored.

Can you try to reproduce the problem outside of JSON Forms? So check whether your AJV instance works, for example like this:

const validator = ajv.compile(schema);
const errors = validator(data)

Please also check the “Vanilla” AJV, i.e.

const validator  = new Ajv().compile(schema)

Please also note that the options you hand over to AJV are outdated, please see here.