dschnelldavis / angular2-json-schema-form

Angular 2 JSON Schema Form builder
MIT License
285 stars 177 forks source link

Data-only mode throws on init. #287

Open mringer opened 6 years ago

mringer commented 6 years ago

Issue type

I'm submitting a (check one): [x] Bug report [ ] Feature request [ ] Regression (something that used to work, but stopped working in a newer version) [ ] Support request [ ] Documentation issue or request

Prerequisites

Before posting, make sure you do the following (check all): [x] Confirm you are using the latest versions of all necessary packages (or if not, explain why not) [x] Search GitHub for a similar issue or PR [x] If submitting a Support request, also search Stack Overflow for similar issues Note: Please cross-post GitHub support requests to Stack Overflow, and include a link in your GitHub issue to your Stack Overflow question. We do currently respond to support requests on GitHub, but we eventually expect to stop, and will then refer all support questions exclusively to Stack Overflow.

Current behavior

Using the configuration provided in the documentation creating a "Data Only" with no schema or layout defined throws.

     JsonSchemaFormComponent
     Error: no schema with key or ref "http://json-schema.org/draft-06/schema#"
    at Ajv.validate (webpack:////Users/.../dev/github/.../.../web-app/node_modules/angular2-json-schema-form/node_modules/ajv/lib/ajv.js?:92:19)
    at Ajv.validateSchema (webpack:////Users/.../dev/github/.../.../web-app/node_modules/angular2-json-schema-form/node_modules/ajv/lib/ajv.js?:178:22)
    at Ajv._addSchema (webpack:////Users/.../dev/github/.../.../web-app/node_modules/angular2-json-schema-form/node_modules/ajv/lib/ajv.js?:312:10)
    at Ajv.compile (webpack:////Users/.../dev/github/.../.../web-app/node_modules/angular2-json-schema-form/node_modules/ajv/lib/ajv.js?:112:24)

Expected behavior

Expect a form to be created mirroring the JSON doc provided as input.

IMPORTANT: How can we reproduce your problem?

import { ComponentFixture, fakeAsync, TestBed } from '@angular/core/testing';
import {
  MaterialDesignFrameworkModule,
  JsonSchemaFormModule,
  JsonSchemaFormService,
  FrameworkLibraryService,
  WidgetLibraryService,
  Framework,
  MaterialDesignFramework } from 'angular2-json-schema-form';

import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';

/* tslint:disable:component-class-suffix */
describe('JsonSchemaFormComponent', () => {

  let fixture: ComponentFixture<JsonSchemaFormBasicUsage>;
  let component: JsonSchemaFormBasicUsage;

  beforeEach(fakeAsync(() => {

    TestBed.configureTestingModule({
      declarations: [
        JsonSchemaFormBasicUsage
      ],
      imports: [
        MaterialDesignFrameworkModule,
        {
          ngModule: JsonSchemaFormModule,
          providers: [
            JsonSchemaFormService,
            FrameworkLibraryService,
            WidgetLibraryService,
            {provide: Framework, useClass: MaterialDesignFramework, multi: true}
          ]
        }
        // New Widgets must import their dependencies.
      ],
      providers: []
    })
    .compileComponents();

    fixture = TestBed.createComponent(JsonSchemaFormBasicUsage);
    component = fixture.componentInstance;
  }));

  fit('should build the json-schema-form basic usage', () => {

    fixture.detectChanges();
    expect(component).toBeTruthy();

  });

});

@Component({
  template: `
  <json-schema-form
    loadExternalAssets="true"
    [(ngModel)]="exampleJsonObject">
  </json-schema-form>
  `
})

class JsonSchemaFormBasicUsage {

  exampleJsonObject: any;

  constructor() {
    this.exampleJsonObject = {
      'first_name': 'Jane', 'last_name': 'Doe', 'age': 25, 'is_company': false,
      'address': {
        'street_1': '123 Main St.', 'street_2': null,
        'city': 'Las Vegas', 'state': 'NV', 'zip_code': '89123'
      },
      'phone_numbers': [
        { 'number': '702-123-4567', 'type': 'cell' },
        { 'number': '702-987-6543', 'type': 'work' }
      ], 'notes': ''
    };
  }

}

Environment

OS name & version: OS X 10.13.4 Browser name & version: Chrome 66.0.3359.181 Angular version: 5.1.0 Angular JSON Schema Form version(s): 0.7.0-alpha.1 Other relevant software or packages:

Any other relevant information

catull commented 6 years ago

@mringer The trick is to initialise ajv to be aware of draft6 of JSON schema.

Check out my repo angular2-json-schema-form-issue-287.

It does not run on StackBlitz yet: https://stackblitz.com/github/catull/angular2-json-schema-form-issue-287.

Locally, it starts up nicely.

This is the improvements I made.

  1. Copied draft 6 of JSON schema to src/app.schema.draft6.ts
  2. Marked up the JSON schema form component to be accessible as #jsonSchemaFormComponent
  3. implemented OnInit to register draft 6 with ajv directly with #jsonSchemaFormComponent (\@ViewChild)

Good luck.

mringer commented 6 years ago

@catull thanks for the tip, sounds like this is something that should be wrapped by a service and provided by the a2-jsf module when it bootstraps.

catull commented 6 years ago

@mringer Either that, or there could be an initialisation hook that hands you an ajv instance and you can perform any action.

Something like this

<json-schema-form
    loadExternalAssets='true'
    [(ngModel)]='exampleJsonObject'
    initialise='initialise(ajv)'>
</json-schema-form>

You would implement the method in your component

initialise (ajv): void {
  // ajv.addMetaSchema(.....);
  // ajv.addSchema(.....);
  // etc
}
mringer commented 6 years ago

Sure, but this step really should be performed as part of the library's bootstrap, rather than having the library user perform additional configuration steps. Especially if it is something the library expects to perform it's baseline behavior.

catull commented 6 years ago

@mringer I have around 20 schemata, most of them are independent. A few reference one of the other schemata.

All of them must be "spoon-fed" upfront to ajv, first all $ref-ed ones, then all the other ones. Without the trick above, I get a lot of runtime errors about schema A not being known when $ref-ed from Schema B etc.

I do agree with you that all draft JSON schemata (v4, v5, v6, v7 and soon v8) MUST be registered with ajv - you refer to it as bootstrapping. That is the responsibility of angular2-json-schema-form.

mringer commented 6 years ago

@catull super useful stuff. Thanks! I incorporated, your suggestion into my angular2-json-schema-form wrapper and it works like a charm. This underscores the need for unit testing in angular2-json-schema-form. I'm working on a PR for a TDD harness.

catull commented 6 years ago

@mringer Allow me to suggest to switch to ng-json-schema-form, a fork by Shamoon Siddiqui

He announced to carry on with angular2-json-schema-form here. In that issue, you will learn that angular2-json-schema-form is pretty much unmaintained.

Shamoon has already incorporated one PR in his fork, and released a new version, see https://www.npmjs.com/package/ng-json-schema-form

mringer commented 6 years ago

fair enough, thanks for the heads up.