How to submit and check if form is valid (angular)

I am playing around with jsonforms-angular-seed.
Everything is working fine, but how do I implement a submit button?
I did not find any examples about this.
I can add a button with an onclick handler but how do I then access the form component?

1 Like

Hi @cornelos,

we output (@Output) dataChange and errors, see here.

Ah yes, I see.

Another related question then.

I have a very simple form with some required text fields.
(Angular, Material render)

When the form is displayed it shows the ‘Is a required property’ message for the fields (this is what I expect)

initial

Then, when I enter some text the error message disappears (also expected):

filled

But if I clear the text fields again it does not show the required-error anymore.
The errors event (errors)="onErrors($event)" is reporting 0 errors. This is not what I expected.
Can you explain this?

empty

1 Like

I’m also confused by this aspect too. I’m trying to have error messages shown after being touched, I’ve tried to override the onChange method in my custom renderers, but I’m having no luck. Very confused as to how and when the errors are emitted.

I found a work around, but I feel there must be a better way to do this. Within my customer renderer I implemented ngAfterViewInit in which I called:
this.jsonFormsService.updateCore(
Actions.update(this.propsPath, () => this.value)
);
Where value is binded to the input control, which also has the focus directive which will toggle a variable isTouched.

<input
[ngStyle]="{‘width’: ‘17%’}"
[id]=“id”
[formControl] =“form”
type=“date”
class=“form-control”
(input)=“onChange($event)”
[(ngModel)]=“value”
(focus)=“onFocus($event)”>

the onFocus method:
onFocus(ev: any){
this.isTouched = true;
}

Please let me know if there is a cleaner/more efficient way to implement this. Thanks!

The validator required validates NULL, but an empty/cleared input has a value of “” - an empty string.
Since I have custom renderers, I map the output data to NULL if it is an empty string.

1 Like

Hi @Jayrack813,

I think in general your approach is correct, i.e. to not show an error until an input is touched, each input needs to track whether it was already touched.

However I’m not sure why you need to dispatch an update on ngAfterViewInit?

Hey Stefan,

I used ngAfterViewInit to update because if you render the form, without updating the user can click the submit button without any errors being emitted. Using ngAfterViewInit to update allowed for the errors array to be emitted which then allowed me to restrict the using from submitting the form. I have a further question regarding this: Is it possible to have an independent submit button that will validate when clicked? When clicked, it would access the formControls and markAllAsTouched for example. Ideally I would like error messages to appear when an input field is touched and dirty, and also if the user hits the submit button.

Thanks!

Thanks for the tip Ketec!

I managed to make it work by doing this:

override ngOnInit () {
    super.ngOnInit();
    this.form.valueChanges.pipe(debounceTime(300)).subscribe(val => {      
      if (val==='') {
        this.form.setValue(null, {emitEvent: false});        
        this.jsonFormsService.updateCore(Actions.update(this.propsPath, () => null));
      }
    });
  }

No, I was wrong, this solution is not working as I expected.
If set the value to form.errors becomes: {"error":"must be string"}
instead of: {"error":"is a required property"}

I used a override for mapToProps of the JsonFormsControl

  protected mapToProps(state: JsonFormsState): StatePropsOfControl {
    const props = super.mapToProps(state);
    return {
      ...props,
      data: props.data ?? null
    };
  }

Hi Cornelos, I made a little change to your solution and it works as expected.

this.fieldName = (this.id).substring(this.id.lastIndexOf('/') + 1);
this.form.valueChanges.pipe(debounceTime(300)).subscribe(val => {      
            if (val==='') {
              const currentFormData = this.jsonFormsService.getState().jsonforms.core.data;
              delete currentFormData[this.fieldName];
              this.jsonFormsService.setData(currentFormData);
            }
 });
1 Like