chebad
chebad

Reputation: 1017

Dynamically create forms from JSON Schema

I'm struggling with creating dynamically forms from JSON Schema in Angular 8. I found some libraries for that, but one is very old (last commit ~2 yr ago) and fork of it from this year.

I don't want to use first one, because it's deprecated with angular 8, so my choise was the second one. I have trouble because this project isn't on any npm repositories, only on github. I downloaded it form git like this:

npm i rhalff/angular2-json-schema-form#angular-8

When I started to build my project with this dependency and after attach the import into app.module.ts the result is like this:

ERROR in src/app/app.module.ts:20:65 - error TS2307: Cannot find module 'angular2-json-schema-form'.

I found that in node_module there isn't any src or dist folder and then I looked into github projecet and I found that in /.npmignore there is a src.

I have a some solution about that, but it's not the final one and I think is really bad idea. I will locally clone git repository, next then build it with npm run build and then npm link and then npm link <someName> in project catalog.

Is there any solution of this problem? Or any other libraries for converting JSON Schema for Angular 8 forms?

Upvotes: 5

Views: 9522

Answers (1)

Muhammad Ahmar Khan
Muhammad Ahmar Khan

Reputation: 349

You can do something like this. It may not cover some complex scenarios but can do good with less complex forms.

in form.ts

public form: FormGroup = new FormGroup({});
public fields = [
  {label: 'Full Name', name: 'full_name', type: 'text'},
  {label: 'Email', name: 'email', type: 'email'},
  {label: 'Comments', name: 'comments', type: 'textarea'},
]

constructForm(){
    let controls = {};
    fields.map(field => {
       controls[field.name] = new FormControl('');
    });
    this.form = new FormGroup(controls);
  }

in form.html

   <form [formGroup]="form">
     <div *ngFor="let field of fields">
       <label for="{{field.name}}">{{field.label}}</label>
       <div [ngSwitch]="field.type">
    
          <!-- textarea -->
          <textarea *ngSwitchCase="'textarea'" [formControlName]="field.name"></textarea>
    
          <!-- other input fields (text, password, number, email) -->
          <input *ngSwitchDefault id="{{field.id}}" type="{{field.type || 'text'}}" [formControlName]="field.name" />
        </div>
     </div>
   </form>

This is just a basic structure of how I am doing it. You may add more props to field objects even an "on change" handler function and play more. i.e. css_classes, maxlength, and can do in html like field.propName

like:

{label: 'Complex Field', name: 'complex_field, type: 'text', onChange: () => {console.log("Something Happened")}}

And

<input type="{{field.type}} (change)="field.onChange()" [formControlName]="field.name" />

Upvotes: 0

Related Questions