Coder Social home page Coder Social logo

ngx-schema-form's Introduction

Ngx Schema Form Build Status

Ngx Schema Form is an Angular 2+ module allowing you to instanciate an HTML form from a JSON schema.

Note: Version 1.x is compliant with Angular <=4, version 2.x is compliant with Angular >=6.

DISCLAIMER

Ngx Schema Form is not related to angular-schema-form and schemaform.io.

We think angular-schema-form is a great Angular 1 library, and when it will move to Angular 2+, we will probably join our efforts to produce and maintain a unique Angular 2+ solution.

Demo

Demo

Features

  • Generate a form from a single json schema object
  • Generate a form from a default set of html constructs
  • Allow initialization from previous values
  • Validation handled by z-schema
  • Allow injection of custom validators
  • Allow declaration of custom widgets
  • Allow injection of custom bindings (new!)

Installation

To use Ngx Schema Form in your project simply execute the following command:

npm install ngx-schema-form --save

You just have to check that all the peer-dependencies of this module are satisfied in your package.json.

JSON Schema

With the installation there comes a JSON-Schema file that declares all specific or additional properties supported by ngx-schema-form.

When using *.json files you may declare it with the $schema property to let your IDE's autocompletion help you create a schema-form.

{
  "$schema": "./node_modules/ngx-schema-form/ngx-schema-form-schema.json",
  "title": "My awesome schema-form"
  ...
}

Getting started

Here our goal will be to create a simple login form. Let's start by creating a simple AppComponent taking a simple JSON schema as input.

// app.component.ts

import { Component } from "@angular/core";
import { ISchema } from 'ngx-schema-form';

@Component({
  selector: "minimal-app",
  // Bind the "mySchema" member to the schema input of the Form component.
  template: '<sf-form [schema]="mySchema"></sf-form>',
})
export class AppComponent {
  // The schema that will be used to generate a form
  mySchema: ISchema = {
    properties: {
      email: {
        type: "string",
        description: "email",
        format: "email",
      },
      password: {
        type: "string",
        description: "Password",
      },
      rememberMe: {
        type: "boolean",
        default: false,
        description: "Remember me",
      },
    },
    required: ["email", "password", "rememberMe"],
  };
}

Create a module which import the AppComponent and configure Ngx schema form.

//app.module.ts

import { NgModule } from "@angular/core";
import { BrowserModule } from "@angular/platform-browser";
import {
  SchemaFormModule,
  WidgetRegistry,
  DefaultWidgetRegistry,
} from "ngx-schema-form";
import { AppComponent } from "./app.component";

@NgModule({
  imports: [SchemaFormModule.forRoot(), BrowserModule],
  declarations: [AppComponent],
  providers: [{ provide: WidgetRegistry, useClass: DefaultWidgetRegistry }],
})
export class AppModule {}

The code above creates a form with three required fields. The validation state of each field is reflected by the class of each of them which can be either "has-error" or "has-success". Validation is done everytime a field's value changes. Basic validation is made by testing the value of the field against its corresponding schema. The input schema support almost all the features listed on the JSON schema specification.

Accessing the form's value

Input binding

It is possible to provide initial values to the form. You can set the initial form's value through the model input:

@Component({
template: '<sf-form [schema]="mySchema" [model]="myModel"></sf-form>'
})
export class AppComponent {
  mySchema = {...};
  myModel = {email:" [email protected]"};
}

Output binding

The Form component provides the onChange output binding of which value represents the value of the form. For instance, you can display the current forms's value with the following template:

template: '<sf-form [schema]="mySchema" (onChange)="value=$event.value"></sf-form>{{value | json}}';

The model property allow two-way data binding:

<sf-form [schema]="mySchema" [(model)]="value"></sf-form>{{value | json}}

Widgets

Each field can be displayed using a specific widget. To declare the widget you want to use, add its id to the field's definition:

mySchema = {
  properties: {
    email: {
      type: "string",
      description: "email",
      format: "email",
    },
    password: {
      type: "string",
      description: "Password",
      widget: "password", // == "widget": {"id": "password"}
    },
    rememberMe: {
      type: "boolean",
      default: false,
      description: "Remember me",
    },
  },
};

If there is no widget declared in a given property's schema, its type is used as widget id and the default registry gives a default widget (see details below). For instance, a string property will use the "string" widget. The following JSON schema is equivalent with the above example:

mySchema = {
  properties: {
    email: {
      type: "string",
      description: "email",
      format: "email",
      widget: "string",
    },
    password: {
      type: "string",
      description: "Password",
      widget: "password", // == "widget": {"id": "password"}
    },
    rememberMe: {
      type: "boolean",
      default: false,
      description: "Remember me",
      widget: "boolean",
    },
  },
};

Some widgets accept parameters as input, in such cases, it is possible to provide them in the schema directly within the widget property (here the TinyMCE widget ):

mySchema = {
  properties: {
    pageContent: {
      type: "string",
      description: "Page content",
      widget: {
        id: "richtext",
        plugins: "textcolor colorpicker",
        toolbar: "forecolor backcolor",
      },
    },
  },
};

Default widget's registry

Available widgets are managed through a WidgetRegistry. The default registry (DefaultWidgetRegistry) contains many widgets listed below, ordered by type:

  • string: string, search, tel, url, email, password, color, date, date-time, time, textarea, select, file, radio, richtext
  • number: number, integer, range
  • integer: integer, range
  • boolean: boolean, checkbox

Note that the select and radio widgets rely on the oneOf property:

"operatingSystem": {
  "type": "string",
  "oneOf": [
    {
      "enum": [
        "linux"
      ],
      "description": "GNU/Linux"
    },
    {
      "enum": [
        "osx"
      ],
      "description": "OSX"
    },
    {
      "enum": [
        "windows"
      ],
      "description": "Windows"
    },
    {
      "enum": [
        "other"
      ],
      "description": "Other"
    }
  ],
  "default": "other"
}

Actions and buttons

Each schema can be extended by adding buttons after its widget.

// app.component.ts
@Component({
  selector: "minimal-app",
  // Bind the actions map to the the "actions" input
  template: '<sf-form [schema]="mySchema" [actions]="myActions"></sf-form>',
})
export class AppComponent {
  // The schema that will be used to generate a form
  mySchema = {
    properties: {
      email: {
        type: "string",
        description: "email",
        format: "email",
      },
      password: {
        type: "string",
        description: "Password",
        buttons: [
          {
            id: "reset",
            label: "Reset",
          },
        ],
      },
      rememberMe: {
        type: "boolean",
        default: false,
        description: "Remember me",
      },
    },
    required: ["email", "password", "rememberMe"],
    buttons: [
      {
        id: "alert", // the id of the action callback
        label: "Alert !", // the text inside the button
      },
    ],
  };

  // Declare a mapping between action ids and their event listener
  myActions = {
    alert: (property) => {
      alert(JSON.stringify(property.value));
    },
    reset: (property) => {
      property.reset();
    },
  };
}

Render buttons

You may define you own widget to create buttons by overriding the default widget for action buttons or create completely customized button widgets.

Override

Override the default action button widget in your WidgetRegistry implementation and register your own button widget.

this.register("button", MyButtonWidgetComponent);
Custom

Define a custom button widget by setting the property button.widget in the schema

  "password": {
    "type": "string",
    "description": "Password",
    "buttons": [
      {
        "id": "reset",
        "label": "Reset"
      },
      {
        "id": "custom_b",
        "label": "My custom button",
        "widget": "my_custom_button" // custom widget name for this button
      }
    ]
  }

and then register it in your WidgetRegistry implementation

this.register("my_custom_button", MyCustomButtonWidgetComponent);
Binding

The button widget will get provided the button object form the schema including the button.action from the action registry and the formProperty object.

To be fully AOT compatible the custom button widget may then extend ButtonWidget or provide the properties button and formProperty by it self.

import { Component } from "@angular/core";
import { ButtonWidget } from "ngx-schema-form/dist/defaultwidgets";

@Component({
  selector: "sf-button-widget",
  templateUrl: "custom-button.widget.html",
})
export class CustomWidgetComponent extends ButtonWidget {}
  @Component({
    selector: 'sf-button-widget',
    templateUrl: 'custom-button.widget.html'
  })
  export class CustomWidgetComponent {
    public button
    public formProperty
  }

Advanced validation

JSON schema provides validation against a static schema but its often necessary to provide other validation rules. The Form component accepts a validators input bound to a map between a field id and a validation function. The validation function takes three arguments: the value of the field, the property corresponding to it and the form object.

In the following example we create a simple registration form. The user have to enter his password twice. To perform this check we create a custom validator:

@Component({
  selector: "minimal-app",
  // Bind the validator map to the the "validators" input
  template:
    '<sf-form [schema]="mySchema" [validators]="myValidators"></sf-form>',
})
export class AppComponent {
  mySchema = {
    properties: {
      email: {
        type: "string",
        description: "email",
        format: "email",
      },
      password: {
        type: "string",
        description: "Password",
      },
      passwordCheck: {
        type: "string",
        description: "Password (verification)",
      },
    },
    required: ["email", "password", "passwordCheck"],
  };

  // Declare a mapping between action ids and their implementations
  myValidators = {
    "/passwordCheck": (value, property, form) => {
      const passwordProperty = formProperty.findRoot().getProperty("password");
      if (
        passwordProperty.value !== undefined &&
        property.valid &&
        value !== passwordProperty.value
      ) {
        return { passwordCheck: { expectedValue: "same as 'password'" } };
      }
      return null;
    },
  };
}

Custom Bindings

Some form field may require a reaction to other forms fields when getting some input. The Form component accepts a bindings input bound to a map of field paths mapped to event and binding functions.
The binding function takes two arguments: the native event, and the property corresponding to it.

The following example creates a form where you will fill in some data for a family. When you type in the name of the parent (first person) the name of the children will be kept updated.

@Component({
  selector: "minimal-app",
  // Bind the bindings map to the the "bindings" input
  template:
    '<sf-form [schema]="mySchema" [bindings]="myFieldBindings"></sf-form>',
})
export class AppComponent {
  mySchema = {
    type: "object",
    title: "Example with custom bindings.",
    description:
      "Type a family name to see how the name gets synchronized with the children.",
    properties: {
      name: {
        type: "string",
        title: "Surname",
      },
      forename: {
        type: "string",
        title: "Forename",
      },
      children: {
        type: "array",
        title: "Family",
        items: {
          type: "object",
          title: "Children",
          properties: {
            name: {
              type: "string",
              title: "Surname",
            },
            forename: {
              type: "string",
              title: "forename",
            },
            age: {
              type: "number",
              title: "age",
            },
          },
        },
      },
    },
  };

  // Declare a mapping between field and event-id
  myFieldBindings = {
    "/name": [
      {
        input: (event, formProperty: FormProperty) => {
          const parent: PropertyGroup = formProperty.findRoot();

          /**
           * Set the input value for the children
           */
          const child1: FormProperty = parent.getProperty("children/0/name");

          child1.setValue(formProperty.value, false);

          const child2: FormProperty = parent.getProperty("children/1/name");
          child2.setValue(event.target.value, false);

          /**
           * Get the input value for all the children
           */
          for (const objectProperty of parent.getProperty("children")
            .properties) {
            console.log(
              "Value for child ",
              objectProperty,
              objectProperty.properties["name"].value
            );
          }
        },
      },
    ],
  };
}

Conditional fields

It is possible to make the presence of a field depends on another field's value.
To achieve this you just have to add a visibleIf property to a field's definition.

Value
The value to match is set as array item.
Setting multiple items will make the visiblity condition true if one of the values matches.
If it is required to match all values head over to the section visibleIf with allOf condition.

$ANY$
Adding the value $ANY$ to the array of conditional values, will make the field visible for any value inserted.

@Component({
  selector: "minimal-app",
  template: '<sf-form [schema]="mySchema"></sf-form>',
})
export class AppComponent {
  mySchema = {
    properties: {
      name: {
        type: "string",
        description: "Username",
      },
      comment: {
        type: "string",
        description: "Comment",
      },
      registerNewsletter: {
        type: "boolean",
        description: "I want to receive the newsletter",
        default: false,
        visibleIf: {
          comment: ["$ANY$"],
        },
      },
      registerEmail: {
        type: "string",
        description: "Email",
        format: "email",
        // Declare that this field must be displayed only if registerNewsletter is true
        visibleIf: {
          registerNewsletter: [true],
        },
      },
    },
    required: ["name", "comment", "registerToNewsletter"],
  };
}

$EMPTY$
Assigning an empty Object to 'visibleIf' is interpreted as visibleIf nothing, thereby the widget is hidden and not present in model.

mySchema = {
  properties: {
    hidden: {
      type: "boolean",
      visibleIf: {},
    },
  },
};

visibleIf may also declare conditional binding by using oneOf or allOf properties. Where oneOf is handled as OR and allOf is handled as AND.

  "visibleIf": {
        "allOf": [
          {
            "forename": [
              "$ANY$"
            ]
          },
          {
            "name": [
              "$ANY$"
            ]
          }
        ]
      }

The oneOf a is prioritized before the allOf and both are prioritized before the property binding.

Chaining of oneOf and allOf is possible like in the example below:

"visibleIf": {
  "allOf": [
    {
      "oneOf": [{ "/demo/visibleIfBinding1/status1a": ["Pass"] }, { "/demo/visibleIfBinding1/status1b": ["Pass"] }]
    },
    {
      "oneOf": [{ "/demo/visibleIfBinding1/status1c": ["Pass"] }, { "/demo/visibleIfBinding1/status1d": ["Pass"] }]
    }
  ]
}

oneOf and allOf are reserved keywords and not suitable as property names

Arrays

To address array items or not yet existing properties the visibleIf condition path may contain wildcard *.

e.g

  "visibleIf": {
        "oneOf": [
          {
            "/person/*/age": [
              "18"
            ]
          }
        ]
      }

To address a specific item the visibleIf condition path should contain the index position.

e.g

  "visibleIf": {
        "oneOf": [
          {
            "/person/1/age": [
              "18"
            ]
          }
        ]
      }

Expressions

Expressions allow a more complex visibleIf condition related to the involded fields.
To use an expression the value of the item
in the conditional array must start with $EXP$.
When processing the expression a context is available containing
a source and a target object.
Where source is the FormProperty that has the visibleIf condition defined
and target is the FormProperty that has been defined by the path.

  "myField" : { // SOURCE
    "visibleIf": {
          "oneOf": [
            {
              "/person/1/age": // TARGET
              [
                "$EXP$ target.value < 18"
              ]
            }
          ]
        }
   }

Hidden fields

When a field has been made invisible by the condition visibleIf then the property of the invisible field will be missing in the result model.

If there is need to submit default values that are not visible for the form the widget.id hidden might be the better choice

  mySchema = {
    "properties": {
      "hiddenInput": {
        "type": "boolean",
        "widget": "hidden",
        "default": true
      },
      "lastName": {
        "type": "string",
        ...
      }
    }
  }

so the value of the hidden field will be bound to the output model

  {
    "hiddenInput": true,
    "lastName": "Doe",
    ...
  }

Fields presentation and ordering

As a JSON object is an unordered collection you can't be sure your fields will be correctly ordered when the form is built. The order and fieldsets entries of the schema are here to organize your fields.

Ordering

The order entry is an array listing all the fields ids in the order they must appear in the form:

{
  "properties": {
    "firstName": {"type": "string","description": "First name"},
    "lastName": {"type": "string","description": "Last name"},
    "email": {"type": "string","description": "Email"}
  },
  "order": ["firstName", "lastName", "email"]
}

Fieldsets

With the fieldsets property, you can describe the different parts of the form and the fields they contain:

{
  "properties": {
    "firstName": {
      "type": "string",
      "description": "First name"
    },
    "lastName": {
      "type": "string",
      "description": "Last name"
    },
    "email": {
      "type": "string",
      "description": "Email"
    },
    "notificationsFrequency": {
      "type": "string",
      "description": "Notifications frequency",
      "widget": "select",
      "oneOf": [
        {
          "description": "Daily",
          "enum": [
            "daily"
          ]
        },
        {
          "description": "Weekly",
          "enum": [
            "weekly"
          ]
        },
        {
          "description": "Monthly",
          "enum": [
            "monthly"
          ]
        }
      ],
      "default": "daily"
    }
  },
  "fieldsets": [
    {
      "title": "Personal information",
      "fields": [
        "firstName",
        "lastName",
        "email"
      ]
    },
    {
      "title": "Account settings",
      "fields": [
        "notificationsFrequency"
      ]
    }
  ]
}

The title entry of each fieldset is optional.

Fixing the schema or model before rendering

Sometimes your schema (or model) is provided by a backend you cannot control. If it is not formatted the way Angular 2 Schema Form expects or if some elements are missing (for instance the fieldsets, some widgets, etc.), you can fix it very easily in your component:

@Component({
  selector: 'plone-view-edit',
  template: '<sf-form [schema]="schema" [model]="model" [actions]="actions"></sf-form>'
})
export class MyComponent {
  private schema: any = {
    'properties': {}
  };
  private actions: any = {};
  private model: any = {};

  constructor(private http: Http) { }

  ngOnInit() {
    this.http.get('http://mybackend/schema').subscribe(res => {
      let schema = res.json();

      // FIXES
      // the "description" field must be rendered with tinymce
      schema.properties.description.widget = 'tinymce'

      // the "publication" field is required
      schema.required = ['publication'];

      this.schema = schema;
    });
  }
}

Creating a custom widget

Ngx schema form allows you to create your own widget.

Note: Currently this feature is not completely defined and the API might change.

You need to derivate the widget you want to customize:

@Component({
  selector: "mdl-sf-string-widget",
  templateUrl: "./string.widget.html",
})
export class MyStringWidget extends StringWidget {}

You need to provide its html template (let's imagine we want to use the Material Design text field):

<mdl-textfield
  [label]="schema.description"
  type="string"
  floating-label
  [name]="name"
  [attr.readonly]="schema.readOnly?true:null"
  [attr.id]="id"
  [attr.disabled]="schema.readOnly?true:null"
  [formControl]="control"
></mdl-textfield>

And you need to declare it in a custom registry:

import { MyStringWidget } from "./mystring";

export class MyWidgetRegistry extends DefaultWidgetRegistry {
  constructor() {
    super();

    this.register("string", MyStringWidget);
  }
}

And, in your module, you need to:

  • declare your widget component (like any regular component),
  • declare it as an entry components (it means it can be instanciated dynamically),
  • and provide your registry.
declarations: [MyStringWidget],
entryComponents: [MyStringWidget],
providers: [{provide: WidgetRegistry, useClass: MyWidgetRegistry}],

Note: you will also need to import ReactiveFormsModule if you want to be able to use form control:

import { ReactiveFormsModule } from '@angular/forms';
...
@NgModule({
  ...
  imports: [
    ...
    ReactiveFormsModule,
  ]
})

Create form from html instead of json schema

Ngx schema form allows you to create forms from angular html templates too. For this you only need to import TemplateSchemaModule to your app, and use the directive templateSchema on sf-form.

The followin html will generate the same form as the json schema in getting started section.

<sf-form [(ngModel)]="model" templateSchema>
  <sf-field name="email" format="email" [required]="true"> Email </sf-field>
  <sf-field name="password" widget="password" [required]="true">
    Password
  </sf-field>
  <sf-field name="rememberMe" type="boolean"> Remember Me </sf-field>
</sf-form>

For more details see example app.

Development and build

To work on this package:

npm install

Then you can build:

npm run build:lib

If you want to work with the demo:

npm install -g @angular/cli
npm install
ng build schema-form
npm start

Building the API documentation

You can build an HTML version of the API documentation by running the following command:

npm run typedoc

The api is then available in the "doc" directory.

ngx-schema-form's People

Contributors

aharaguchi avatar akloeber avatar almogshaul avatar anotherpit avatar artonio avatar avifix avatar bennmapes avatar cardioprint avatar cv-avig avatar daniele-pecora avatar dependabot[bot] avatar dmastag avatar ebrehault avatar fbessou avatar felixbaral avatar iamtomcat avatar invis1ble avatar iperevozchikov avatar jackrvaughan avatar jmsegrev avatar kbroichhausen avatar mchapman avatar monstrfolk avatar pankyka avatar sbats avatar sunew avatar vangheem avatar whiletrueendwhile avatar yoraco avatar zheyangsong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ngx-schema-form's Issues

Bad naming for textline and text widgets

'textline' is supposed to be a single-line text (= input type="text") while 'text' is supposed to be a multiline text (=textarea)

(and textline should be the default widget for string fields)

Usage from an external project

@fbessou we start thinking about making a releasable bundle, so angular2-schema-form could be used as an external dependency in any regular project.
But we do not need a bundle here, we just need the .ts files, because the project will have its own webpack setup to compile everything anyway.

Nevertheless, we need to clean up our dependencies (some are declared as devDependencies but should not, like z-schema).

A suggestion for collaboration

Hi,
We would like to collaborate and contribute to your project.
We have ideas to enrich the form capabilities.
Are you interested?

Shaul Almog
Sapiens Technologies

readOnly not working as expected

  • if I add "readOnly": false to a property with type boolean it still gets disabled
  • arrays ignore readonly completely. They are always enabled.

And a small question: Is there a way to make the whole form readonly?

$ref does not work

Trying to use this data to create a form and I get the following error:

ORIGINAL EXCEPTION: Undefined type undefined

If I copy the properties from the registers definition into the registers property, it displays the input just fine. Is this not supported or am I doing it wrong?

{
    "title": "Device Template",
    "definitions": {
        "registers": {
            "type": "object",
            "properties": {
                "perm": {
                    "type" : "string"
                }
            }
        }
    },
    "type": "object",
    "properties": {
        "deviceaddr": {
            "description": "Device Address",
            "type": "string"
        },
        "registers": { "$ref": "#/definitions/registers" }
    },
    "required": [ "deviceaddr" ]
}

Integration with angular2 project

Hello,

I'm trying to integrate angular2-schema-form in an angular2 project. It worked well until I fetched the latest commit ("Apply new project base from change-project-base"). The demo runs OK.
The error is :

Error: (SystemJS) XHR error (404 Not Found) loading http://localhost:3000/node_modules/angular2-schema-form/dist/schema-form/model.js
patchProperty/desc.set/wrapFn@http://localhost:3000/node_modules/zone.js/dist/zone.js:889:26 []
Zone.prototype.runTask@http://localhost:3000/node_modules/zone.js/dist/zone.js:151:28 [ => ]
ZoneTask/this.invoke@http://localhost:3000/node_modules/zone.js/dist/zone.js:345:28 []

Error loading http://localhost:3000/node_modules/angular2-schema-form/dist/schema-form/model.js as "./model" from http://localhost:3000/node_modules/angular2-schema-form/dist/schema-form/form.component.js

As you can see, I'm using SystemJS.

Do you have any idea that could help ?

Thank you,

Use existing form instead of creating a whole new one

To be able to split up code and validation (frontend/backend) development, it would be a nice feature to allow mapping of a JSON schema form to an existing form, f.e. mapping could be done via ids of input fields or name.

angular2-schema-form 404 (Not Found)

When adding the FieldRegistryService at bootstrap i get the following error:

zone.js:101 GET http://localhost:4200/angular2-schema-form 404 (Not Found)

I am using angular cli.

//main.ts
import { bootstrap } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { AppComponent, environment } from './app/';
import { HTTP_PROVIDERS } from '@angular/http';
import { appRouterProviders } from './app/app.routes';
import { FieldRegistryService } from "angular2-schema-form";

if (environment.production) {
  enableProdMode();
}

bootstrap(AppComponent, [appRouterProviders, HTTP_PROVIDERS, FieldRegistryService]);

Any idea what might be missing?

Using with Angular 2.1.2

When I am trying to start demo-example I've got the following error, while npm install

npm WARN EPEERINVALID [email protected] requires a peer of reflect-metadata@^0.1.3 but none was installed.
npm WARN EPEERINVALID [email protected] requires a peer of @angular/[email protected] but none was installed.
npm WARN EPEERINVALID [email protected] requires a peer of @angular/[email protected] but none was installed.
npm WARN EPEERINVALID [email protected] requires a peer of @angular/[email protected] but none was installed.
npm WARN EPEERINVALID [email protected] requires a peer of @angular/[email protected] but none was installed.
npm WARN EPEERINVALID [email protected] requires a peer of @angular/[email protected] but none was installed.
npm WARN EPEERINVALID @angular/[email protected] requires a peer of [email protected] but none was installed.
npm WARN EPACKAGEJSON [email protected] No repository field.

Should I downgrade to a @2.0.0-rc.6 or what is the best solution? thanks in advance

Getting uncaught (in promise) error using Angular2-cli

I followed the instruction how to implement it, although I'm not doing it on app.component.ts I'm implementing it on the actual component which is going to use this.

I'm not sure about the main.browser.ts, but I created that and pasted the code for this file but it still giving me this big error.

Can you shed a light on this error please

Error: Uncaught (in promise): Error: Error in ./InterfaceComponent class InterfaceComponent - inline template:94:19 caused by: Cannot read property 'type' of undefined TypeError: Cannot read property 'type' of undefined at FormComponent.ngOnChanges (http://localhost:3000/main.bundle.js:62933:26) at Wrapper_FormComponent.detectChangesInInputProps (/SchemaFormModule/FormComponent/wrapper.ngfactory.js:54:18) at _View_InterfaceComponent0.detectChangesInternal (/AppModule/InterfaceComponent/component.ngfactory.js:522:29) at _View_InterfaceComponent0.AppView.detectChanges (http://localhost:3000/main.bundle.js:58615:14) at _View_InterfaceComponent0.DebugAppView.detectChanges (http://localhost:3000/main.bundle.js:58720:44) at _View_InterfaceComponent_Host0.AppView.detectViewChildrenChanges (http://localhost:3000/main.bundle.js:58641:19) at _View_InterfaceComponent_Host0.detectChangesInternal (/AppModule/InterfaceComponent/host.ngfactory.js:33:8) at _View_InterfaceComponent_Host0.AppView.detectChanges (http://localhost:3000/main.bundle.js:58615:14) at _View_InterfaceComponent_Host0.DebugAppView.detectChanges (http://localhost:3000/main.bundle.js:58720:44) at ViewRef_.detectChanges (http://localhost:3000/main.bundle.js:41840:20) at resolvePromise (http://localhost:3000/main.bundle.js:81977:31) at http://localhost:3000/main.bundle.js:81954:13 at ZoneDelegate.invoke (http://localhost:3000/main.bundle.js:81741:26) at Object.onInvoke (http://localhost:3000/main.bundle.js:28680:37) at ZoneDelegate.invoke (http://localhost:3000/main.bundle.js:81740:32) at Zone.run (http://localhost:3000/main.bundle.js:81623:43) at http://localhost:3000/main.bundle.js:82011:57 at ZoneDelegate.invokeTask (http://localhost:3000/main.bundle.js:81774:35) at Object.onInvokeTask (http://localhost:3000/main.bundle.js:28671:37) at ZoneDelegate.invokeTask (http://localhost:3000/main.bundle.js:81773:40)

JSON schema looks like this:
{ "type": "object", "properties": { "Name": { "type": "string" }, "Number": { "format": "int32", "type": "integer" }, "PointInTime": { "format": "date-time", "type": "string" }, "Url": { "type": "string" }, "Children": { "type": "array", "items": { "type": "object", "properties": { "ChildName": { "type": "string" }, "ChildNumber": { "format": "int32", "type": "integer" }, "ChildPointInTime": { "format": "date-time", "type": "string" }, "CustomData": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "object" } } } } } }, "CustomData": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "object" } } } } }

Cannot find module 'angular2-schema-form'.

this issue is quite similar to #18

So i was using 1.0.0-alpha.32 and everything is ok , until today i upgrade it to 1.0.0-alpha.33. After the upgrade i received the error Cannot find module 'angular2-schema-form'.

Is there anything else i need to do for the new upgrade? because i notice there is no change done in readme.

thanks!

ERROR in SchemaFormModule is not an NgModule

I am trying to use angular2-schema-form with the latest version of angular-cli.

When I am doing npm start then I am getting this issue : ERROR in SchemaFormModule is not an NgModule

I have checked the issue with angular-cli forums and it is happening with a lot of other modules, and according to what I understood on the forums the angular2 packages in angular2-schema-form need to be updated as well to make it usable with cli projects.

My Angular2-Cli setup:
angular-cli: 1.0.0-beta.24
node: 7.2.1
os: win32 x64
@angular/common: 2.4.1
@angular/compiler: 2.4.1
@angular/core: 2.4.1
@angular/forms: 2.4.1
@angular/http: 2.4.1
@angular/platform-browser: 2.4.1
@angular/platform-browser-dynamic: 2.4.1
@angular/router: 3.4.1
@angular/compiler-cli: 2.4.1

What are your suggestions ?

XHR error angular2-schema-form not found (I'm using rc.5)

Hi,

I'm trying to use this on my application, I followed the installation on the main page and its giving me

Error: Error: XHR error (404 Not Found) loading http://localhost:3000/angular2-schema-form(…)

I'm using SystemJs Config and I also tried adding it in my config js but then it throws an error regarding lodash and validator.

var map = { 'angular2-schema-form': 'node_modules/angular2-schema-form' }
var packages = { 'angular2-schema-form': { main: './dist/index.js', defaultExtension: 'js' }

Can you shed a light on this, please.

Is it possible to have a guide for rc.5 and for systemjs config users?

Thanks

File upload not working

Hi,
While I am trying to upload image file, the json value is coming null.
I am using the below in the json schema. Can you please advise.

"image":{
  "type":"string",
  "widget":"file",
  "media": {
    "binaryEncoding": "base64",
    "type": "image/*"

  }

a lot of errors when build

a lot of error when

npm run build

this is just an extract (the first couple of errors), maybe typings.json is needed?
thx

ERROR in ./src/schema-form/defaultwidgets/array/array.widget.ts
Module not found: Error: Cannot resolve module '@angular/core' in /root/git/angu
lar2-schema-form/src/schema-form/defaultwidgets/array
resolve module @angular/core in /root/git/angular2-schema-form/src/schema-form/d
efaultwidgets/array
  looking for modules in /root/git/angular2-schema-form/node_modules
    /root/git/angular2-schema-form/node_modules/@angular doesn't exist (module a
s directory)
[/root/git/angular2-schema-form/node_modules/@angular]
 @ ./src/schema-form/defaultwidgets/array/array.widget.ts 2:13-37

ERROR in ./src/schema-form/defaultwidgets/object/object.widget.ts
Module not found: Error: Cannot resolve module '@angular/core' in /root/git/angu
lar2-schema-form/src/schema-form/defaultwidgets/object

Force rerendering of the form?

Is there possible to force re rendering of the form, I want to make possible to use multiple schemas, so I can switch them on button click or something like that.

Intergration with 3rd party widget (e.g. primeng, material)

Do you have any means/plans to use primeng widgets?

I am planning to rewrite a java swing ui, which uses xml schema to build its forms. I have chosen angular 2 for the development, and your project combined with primeng looks to me the best solution.

generate the form on click

Hi, is it possible to generate the form on a (click)="generate()" because at first I render my JSON in textarea so I can I edit them then put a button with the function generate() though, I tried doing so using .innerHTML so I can add the whole <schema-form...> within the function but somehow its not generating the form.

my function()
var txtVal = (<HTMLInputElement>document.getElementById('RequestDisplay')).value; this.mySchema = txtVal; console.log(this.mySchema); document.getElementById('jsonForm').innerHTML = '<schema-form [schema]="mySchema" ></schema-form>'

Trying to integrate with Angular 2 Project - Getting error

Hi @kiorky / @ebrehault / @regilero / @jpoliva / @samaradona

I am trying to integrate with a normal Angular 2 project but am getting error when I am trying to add:

import { disableDeprecatedForms, provideForms} from "@angular/forms"
import { WidgetRegistry } from "angular2-schema-form";

bootstrap: [AppComponent,[disableDeprecatedForms(),provideForms(),WidgetRegistry]]

My current project is just a seed project of Angular 2: https://github.com/mgechev/angular2-seed

My requirement is to have some pages dynamic and some pages static. So I tried both bootstrapping inside the the about.module.ts and also inside the app.module.ts

I am pretty new to Angular 2 and not able to find out why the integration is not working. Could you please help in integrating this?

Thank you!

Type check breaks the initialization

The extra code fails when the schema is undefined/null

   if(!this.schema.type) {
      this.schema.type = 'object';
    }

I suppose it should be:

   if(this.schema && !this.schema.type) {
      this.schema.type = 'object';
    }

visibleIf makes fields required

When using "visibleIf" and not specifying which fileds are required it makes the field required. A work around is to sepecify what fields are required and leaving the ones with "visibleIf" out.
this works and name is not required:

            "properties": {
                "consistent": {
                    "type": "boolean",
                    "widget": "checkbox",
                },
                "name": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Name",
                    "title": "Name",
                    "visibleIf": {
                        "consistent": [true]
                    }
                }
            },
            "required": ["consistent"]

But the following doesn't work and name is required:

            "properties": {
                "consistent": {
                    "type": "boolean",
                    "widget": "checkbox",
                },
                "name": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Name",
                    "title": "Name",
                    "visibleIf": {
                        "consistent": [true]
                    }
                }
            }

Form fails to render from the response of http call..

Form renders fine when read from a file. However fails when tried with the response of the http call..

// Observable Version
import { Component, OnInit } from '@angular/core';
import { WidgetRegistry } from "angular2-schema-form";
import { TinyMCEWidget } from "ng2sf-tinymce";
import { Http, Response } from '@angular/http';


@Component({
  selector: 'test-list',
  template: '<schema-form class="col-md-6" [schema]="schemafromhttp" [model]="model" [actions]="actions"></schema-form>',

})
export class TestListComponent {

  errorMessage: string;
  thisSchemaForm: any;
  schemafromfile: any;
  schemafromhttp: any = {'properties': {}, "type": "object"};
  private actions:any = {};
  private model:any = {};

  constructor(private http: Http) {}

  ngOnInit() {
    this.schemafromfile = require("./sampleschema.json");
    console.log("read from file: ", this.schemafromfile);
    console.log("read from file: ", JSON.stringify(this.schemafromfile));
    this.http.get('http://127.0.0.1:8080/getRegSchemaDefinition?type=registration4').subscribe(res => {
      let schemafromhttp1 = res.json();
      schemafromhttp1.fieldsets = [{"fields": ["userID", "appID"]}];
      console.log('read from service: ', schemafromhttp1);
      this.schemafromhttp = schemafromhttp1;
      console.log('read from service: ', JSON.stringify(this.schemafromhttp));
    });
  }
}


the file that renders fine is attached is as, the http response is verified to be same.

{"properties":{"userID":{"type":"string","minLength":7,"maxLength":10,"description":"User ID"},"appID":{"type":"string","minLength":3,"maxLength":3,"description":"Application Identifier"}},"required":["userID"]}

Any heads up if anything specific is missing out?

Subschema

Hello again) Could I use subschema in this module? If it possible, could you show an object example of schema?

__extends is not defined

Using the install instructions, and adding the module to imports or the providers causes this error:

Uncaught ReferenceError: __extends is not defined(…)

If I click on the file where the error is occurring it shows this:

var PropertyGroup = (function (_super) {
    __extends(PropertyGroup, _super);   <<<this line
    function PropertyGroup() {
        _super.apply(this, arguments);
        this.properties = null;
    }
    ...etc

Am I missing something?

Getting error when installing

22181 verbose cwd C:\Users\Nirupama\Downloads\angular2-seed-master\angular2-seed-master
22182 error Windows_NT 10.0.10586
22183 error argv "C:\Program Files\nodejs\node.exe" "C:\Program Files\nodejs\node_modules\npm\bin\npm-cli.js" "install" "angular2-schema-form" "--save-dev"
22184 error node v4.4.7
22185 error npm v2.15.8
22186 error code EPEERINVALID
22187 error peerinvalid The package @angular/[email protected] does not satisfy its siblings' peerDependencies requirements!
22187 error peerinvalid Peer @angular/[email protected] wants @angular/common@^2.0.0-rc.5
22187 error peerinvalid Peer @angular/[email protected] wants @angular/common@^2.0.0-rc.5
22187 error peerinvalid Peer @angular/[email protected] wants @angular/common@^2.0.0-rc.5
22187 error peerinvalid Peer @angular/[email protected] wants @angular/common@^2.0.0-rc.5
22187 error peerinvalid Peer @angular/[email protected] wants @angular/common@^2.0.0-rc.4
22187 error peerinvalid Peer [email protected] wants @angular/[email protected]
22188 verbose exit [ 1, true ]

Please suggest!

Advanced validation did not propagate

Hi,

I tested validations and noticed for the email validator the error is stored in ._errors and in .properties.email._errors. This will cause the error to be send to FormComponent.rootProperty.errorsChanges.subscribe. But when I add my own validation like the passwordCheck this will only be stored on .properties.passwordCheck._errors and the subscription will not get the error. Did I need to configure or change something to let own validators behave like the provided email validator?

Thanks in advance

Custom widget support

After release: 1.0.0-alpha.24, the custom widget example (so called: "wizard") where you could page through the field-set's is not working anymore. In case you have a large json schema which you want to use in this control, then it becomes necessary from a UX perspective to be able to group/page/tab.....things (so as user you get the overview). Can you fix this in a newer release?

Make widget accesible from formProperty

Could a reference to the widget be added to FormProperty, so the widget can be accessed through the provided API and called by custom widgets?

On formelement.component.ts -> onWidgetInstanciated() -> add this.formProperty.widget = this.widget;

Collapsible Group Widget

Hi
I need help to make new widget that take one or more properties and group them in a collapsible section
There is not Wiki for Widget making so I will appreciate your help.

number type gives validation error

I have the following simple schema:

{
	"type": "object",
	"properties": {
		"maxNumberOfRetries": {
			"type": "number",
			"minimum": 0,
			"maximum": 10,
			"description": "Maximum number of retries"
		}
	}
}

This results in a nice numeric field in the UI with up/down spinner buttons.

However when I subscribe to the validation errors like this:

this.subscriptionForErrors = this.schemaForm.rootProperty.errorsChanges.subscribe(e => {
        if(e != null) {
          console.log('errors:');
           e.forEach(ee => console.log(ee));
        }
      });

I get the following error logged when I enter a number in the UI field:
code: INVALID_TYPE
message: Expected type number but found type string

Any idea?

Doesnt work model Change Event

Hello. When, I change value of a key in the model, view not redrawn. It is redrawn when I delete a model, and then re-assigns the object with values.
For example. I have a jsonSchemaForm - input and button. When I clicked on a button I changed value at model, which complies to input. But in view value in input doesnt change.

submit form and enum

Is there a way to submit the form back to the server? Is there any way of binding the inputs?

Also does this support [enum]? something like this
, "Status":{ "enum":[ "Preparing", "AwaitingCompletion", "Cancelled", "Completed" ], "type":"string" },

Just hoping that the module would be something like this
http://brutusin.org/json-forms/#2

required not working ?

The "required" array of the schema doesn't seem to impact the validation of the form.

Am I missing something ?

Ionic 2 Error while building

I'am getting the following error

[23:13:25] ionic-app-scripts 0.0.47
[23:13:25] build prod started ...
[23:13:25] clean started ...
[23:13:25] clean finished in 9 ms
[23:13:25] copy started ...
[23:13:25] ngc started ...
[23:13:28] build prod failed: Unexpected value 'SchemaFormModule' imported by the module 'AppModule'
[23:13:28] ionic-app-script task: "build"
[23:13:28] Error: Unexpected value 'SchemaFormModule' imported by the module 'AppModule'

Here's the system info
node v6.9.2
npm v4.0.5
Angular - 2.2.1
Ionic - 2.0.0-rc.4
angular2-schema-form - 1.0.0-alpha.32

As per this article
Angular Libraries that can utilize ngc require .metadata.json files to be included with the package

more fields in a row

by using the schema (as below):
"fieldsets": [{ "fields": ["student"], "title": "Student" }, {...
the fields of student are showed 1 field per row:

  • row#1) firstname
  • row#2) lastname
  • row#3) id
  • and so on

is there a way to render the form in a different way like (2 fields x row):

  • row#1) firstname, lastname
  • row#2) id, age

it could be nice if bootstrap col classes were supported like:

  • row#1) firstname(col-xs-6), lastname(col-xs-6)
  • row#2) id(col-xs-4), age (col-xs-8)

thanks

array widget change DOM too often

Changes in DOM lead to removing focus from input fields
It makes impossible to type anything
Partially it can be fixed by adding trackBy function to *ngFor
But even after adding trackBy I saw some changes in DOM after clicking to input with ng2-bootstrap typeahead

Unable to start the project

I followed the installation guide but its giving me a bunch of error therefore the project won't run. I did try installing the plugin again see if that works but clearly it didn't.

Any solution to this?

`ERROR in ./src/main.browser.ts
Module build failed: Error: Cannot resolve module 'angular2-schema-form' in C:\Users\mestrada\Desktop\schema-J SON\angular2-schema-form-demo-master\src
Required in C:\Users\mestrada\Desktop\schema-JSON\angular2-schema-form-demo-master\src\main.browser.ts
at ResolutionError.Error (native)
at new ResolutionError (C:\Users\mestrada\Desktop\schema-JSON\angular2-schema-form-demo-master\node_module s\awesome-typescript-loader\dist.babel\deps.js:592:88)
at C:\Users\mestrada\Desktop\schema-JSON\angular2-schema-form-demo-master\node_modules\awesome-typescript- loader\dist.babel\deps.js:400:37
at run (C:\Users\mestrada\Desktop\schema-JSON\angular2-schema-form-demo-master\node_modules\core-js\module s\es6.promise.js:87:22)
at C:\Users\mestrada\Desktop\schema-JSON\angular2-schema-form-demo-master\node_modules\core-js\modules\es6 .promise.js:100:28
at flush (C:\Users\mestrada\Desktop\schema-JSON\angular2-schema-form-demo-master\node_modules\core-js\modu les_microtask.js:18:9)
at nextTickCallbackWith0Args (node.js:420:9)
at process._tickCallback (node.js:349:13)

ERROR in [default] C:/Users/mestrada/Desktop/schema-JSON/angular2-schema-form-demo-master/node_modules/ng2sf-t inymce/dist/src/tinymce.widget.d.ts:1:30
Cannot find module 'angular2-schema-form'.

ERROR in [default] C:/Users/mestrada/Desktop/schema-JSON/angular2-schema-form-demo-master/src/app/app.componen t.ts:2:31
Cannot find module 'angular2-schema-form'.

ERROR in [default] C:/Users/mestrada/Desktop/schema-JSON/angular2-schema-form-demo-master/src/app/app.module.t s:8:7
Cannot find module 'angular2-schema-form'.

ERROR in [default] C:/Users/mestrada/Desktop/schema-JSON/angular2-schema-form-demo-master/src/app/wizard.widge t.ts:1:35
Cannot find module 'angular2-schema-form'.

ERROR in [default] C:/Users/mestrada/Desktop/schema-JSON/angular2-schema-form-demo-master/src/app/wizard.widge t.ts:43:37
Property 'schema' does not exist on type 'WizardWidget'.

ERROR in [default] C:/Users/mestrada/Desktop/schema-JSON/angular2-schema-form-demo-master/src/main.browser.ts: 3:31
Cannot find module 'angular2-schema-form'.
`

Error when importing module in submodule

Hi,

I am receiving an error when trying to use the library in a submodule of my application:
EXCEPTION: Uncaught (in promise): Error: BrowserModule has already been loaded. If you need access to common directives such as NgIf and NgFor from a lazy loaded module, import CommonModule instead.

As per http://stackoverflow.com/a/39414253 I assume that there should be CommonModule included instead of BrowserModule in your schema-form.module.ts.
(Do not import BrowserModule in any other module. Feature modules and lazy loaded modules should import CommonModule instead. They need the common directives. They don't need to re-install the app-wide providers.)

Is there a way around this problem or is this a bug?

I then tried to import the module in my main app.module.ts (not in my sub.module.ts) but then <schema-form [schema]="mySchema"> is simply not rendered.
Can you maybe give me a hint?

Best regards

Chris

Request: Button ID

Hi can you please add a id or something else, for customizing abort / save buttons.
For different button styles. Example

PS. 1.0.0-alpha.29 breaks my build.
[default] /home/sebastian/Dokumente/StuproGUI/app/src/app/app.module.ts:63:48 Cannot find module 'angular2-schema-form'.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.