0

I'm trying to use https://www.npmjs.com/package/@jsonforms/angular-material by running a sample application from https://github.com/eclipsesource/jsonforms-angular-seed.git

The sample application doesn't use routing, but its setup is pretty complicated e.g. using constructor in the app module definition. I tried to follow almost the same to suit my needs also, so it ended up like this:

import {APP_INITIALIZER, NgModule} from '@angular/core';
import { CommonModule } from '@angular/common';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import { RouterModule } from '@angular/router';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { NgxPaginationModule } from 'ngx-pagination';
import { SharedModule } from '../../shared/shared.module';
import {DynamicFormComponent, SchemaEditorDialog} from './dynamic-form.component';
import { DynamicFormData } from './dynamic-form.data';
import {JsonFormsAngularService, JsonFormsModule} from '@jsonforms/angular';
import {Actions, UISchemaElement, setLocale} from '@jsonforms/core';
import { forkJoin } from 'rxjs';
import { parsePhoneNumber } from 'libphonenumber-js';
import { resolveRefs } from 'json-refs';
import AJV from 'ajv';
import { initialState } from './store';
import data from './data';
import {JsonFormsAngularMaterialModule} from '@jsonforms/angular-material';
import {BrowserModule} from '@angular/platform-browser';

export const routes = [
  { path: '', component: DynamicFormComponent, pathMatch: 'full' }
];

export const loadCore = (jsonformsService: JsonFormsAngularService, http: HttpClient): () => Promise<void> => {
  return () => {
    const ajv = new AJV({
      schemaId: 'auto',
      allErrors: true,
      jsonPointers: true,
      errorDataPath: 'property'
    });
    ajv.addFormat('time', '^([0-1][0-9]|2[0-3]):[0-5][0-9]$');
    ajv.addFormat('tel', maybePhoneNumber => {
      try {
        parsePhoneNumber(maybePhoneNumber, 'DE');
        return true;
      } catch (_) {
        return false;
      }
    });

    return forkJoin({
      uischema: http.get('./assets/uischema.json'),
      schema: http.get('./assets/schema.json')
    }).toPromise().then(result => {
      const { schema, uischema } = result;
      return resolveRefs(schema)
          .then(
              (res: any) => {
                jsonformsService.updateCore(
                    Actions.init(
                        data,
                        res.resolved,
                        uischema as UISchemaElement,
                        ajv as any
                    )
                );
              }

          );
    });
  };
};

@NgModule({
  imports: [
    CommonModule,
    HttpClientModule,
    RouterModule.forChild(routes),
    FormsModule,
    ReactiveFormsModule,
    InMemoryWebApiModule.forRoot(DynamicFormData, {delay: 500}),
    NgxPaginationModule,
    SharedModule,
    JsonFormsModule,
    JsonFormsAngularMaterialModule,
    BrowserModule
  ],
  declarations: [
    DynamicFormComponent,
    SchemaEditorDialog
  ],
  schemas: [],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: loadCore,
      deps: [JsonFormsAngularService, HttpClient],
      multi: true
    }
  ]
})

export class DynamicFormModule {
  constructor(jsonformsService: JsonFormsAngularService) {
    jsonformsService.init(initialState.jsonforms);
    jsonformsService.updateLocale(setLocale('de-DE'));
  }
}

And then I got this in Javascript console:

ERROR Error: Uncaught (in promise): ReferenceError: Cannot access 'DynamicFormModule' before initialization
ReferenceError: Cannot access 'DynamicFormModule' before initialization

Google said that it's because of cyclic dependency. But, I checked myself, the component which the module hosts is simple:

@Component({
  selector: 'app-configurations',
  templateUrl: './dynamic-form.component.html',
  styleUrls: ['./dynamic-form.component.scss'],
  encapsulation: ViewEncapsulation.None,
  providers: [ DynamicFormService ]
})
export class DynamicFormComponent implements OnInit {
    public users: FilledFormListItemDto[];
    public searchText: string;
    public page: any;
    public settings: Settings;

    schema: any;
    uiSchema: any;
    data: any;

    constructor(private appSettings: AppSettings,
                private dialog: MatDialog){
        this.settings = this.appSettings.settings;
    }

What did I do wrong? Is there anything I could do to make it much simpler, or perhaps another sample project to refer?

2
  • There are many interesting things going on here: 1. why do you export your router config and loadCore variables? Where else are they used? 2. why child routes (let's see the HTML) 3. why not inject the forms service(s) in the constructor of your app in a similar fashion to the sample you provided? Commented Nov 11, 2020 at 17:44
  • Please put this in a StackBlitz. Commented Nov 11, 2020 at 17:44

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.