mat-dynamic-form
TypeScript icon, indicating that this package has built-in type declarations

1.5.12 • Public • Published

GitHub Workflow Status npm (tag) npm bundle size

Mat Dynamic Form

This is an Angular Material library that was created to make form designing easier and intuitive, you just need to send a json object to generate a fully functional form.

Installation


npm i mat-dynamic-form

Dependencies

Angular Material

Angular Material Documentation


ng add @angular/material

This is necesary to create angular material components.

Usage

AppModule

import { NgModule } from '@angular/core';
import { MatDynamicFormModule } from 'mat-dynamic-form';

@NgModule({
  imports: [
    ...,
    MatDynamicFormModule
  ],
  providers: [],
  ...
})

export class AppModule {}

HTML

<mat-dynamic-form  [structure]="formStructure"></mat-dynamic-form>

TS

This is an example of a full sing up form.

import { Component, OnInit } from '@angular/core';
import { Validators } from '@angular/forms';
import { ActionEvent, Button, Checkbox, CustomNode, DatePicker, Dropdown, FormStructure, Input, InputFile, InputPassword, OptionChild, RadioGroup, TextArea } from 'projects/mat-dynamic-form/src/public-api';
import { InputComponent } from './input/input.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

  formStructure: FormStructure;

  constructor() {
    this.formStructure = new FormStructure();

    this.formStructure.title = 'Sign Up';
    this.formStructure.appearance = 'standard';
    this.formStructure.globalValidators = Validators.required;
    this.formStructure.nodes = [
      new Input('name', 'Name').apply({
        icon: 'person',
        maxCharCount: 100
      }),
      new Button('find', 'Find', { style: 'primary' }).apply({
        icon: "search",
        singleLine: false
      }),
      new Input('tel', 'Phone Number').apply({
        icon: 'phone'
      }),
      new DatePicker('bDate', 'BirthDate').apply({
        action: { callback: this, type: 'change' }
      }),
      new Dropdown('cStatus', 'Civil Status', [
        new OptionChild('Single', 'SI',),
        new OptionChild('Maried', 'MR')
      ]).apply({
        selectedValue: 'SI',
        disabled: true
      }),
      new InputFile('profPic', 'Profile Picture').apply({
        accept: '.png, .jpg, .jpeg'
      }),
      new RadioGroup('hasPet', 'Has Pet', [
        new OptionChild('Yes', 'y'),
        new OptionChild('Not', 'n'),
      ]).apply({
        selectedValue: 'n',
        action: { type: 'valueChange', onEvent: (param) => this.onHasPetValueChange(param) }
      }),
      new InputPassword('pass', 'Password'),
      new TextArea('comments', 'Comments').apply({
        singleLine: true,
        validator: Validators.maxLength(100),
        maxCharCount: 100
      }),
      new CustomNode<InputComponent>('custom1', InputComponent, { label: 'Custom 1', placeholder: 'Custom Placeholder 1' }),
      new CustomNode<InputComponent>('custom2', InputComponent, { label: 'Custom 2', placeholder: 'Custom Placeholder 2' }),
      new Checkbox(
        'agreement',
        `I have read and agree to the terms of DynamicForm License Agreement, <strong><a href='https://www.google.com'>Read the license here.<a </strong>`
      ).apply({
        singleLine: true,
        validator: Validators.requiredTrue
      }),
      new CustomNode<InputComponent>('custom3', InputComponent, { label: 'Custom 3', placeholder: 'Custom Placeholder 2' }),
    ];
    this.formStructure.validateActions = [
      new Button('cancel', 'Cancel', {
        onEvent: (param) => {
          param.structure?.reset();
          param.structure?.remapValues();
        }, style: 'warn'
      }).apply({
        icon: 'close'
      }),
      new Button('save', 'Save', {
        onEvent: (param) => param.structure?.patchValue({ name: 'Carlos', hasPet: 'y' }), style: 'primary',
      }).apply({
        validateForm: true,
        icon: 'save'
      }),
    ];
  }

  ngOnInit(): void {
  }

  onHasPetValueChange(param: ActionEvent) {
    const nodes = [
      new Dropdown('petType', 'Pet Type', [
        new OptionChild('Dog', 'PD'),
        new OptionChild('Cat', 'PC')
      ]),
      new Input('breed', 'Pet Breed'),
      new Input('petName', 'Pet Name')
    ]
    if (param.event == 'y') {
      this.formStructure.createNodes(7, nodes)
    } else this.formStructure.removeNodes(nodes)
  }
}

Custom Component (TS)

This is an example of a custom componente ts child code.

@Component({
  selector: 'app-input',
  templateUrl: './input.component.html',
  styleUrls: ['./input.component.scss']
})
export class InputComponent implements OnInit {
  control: FormControl; // <-- You must have to add this property

  constructor() { }

  ngOnInit() {
  }
}

Custom Component (HTML)

This is an example of a custom componente html child code.

...
<mat-form-field class="col-12" appearance="fill">
  <mat-label>{{label}}</mat-label>
  <input type="email" matInput placeholder="{{placeholder}}" [formControl]="control"> <!-- You must have to bind control property with your custom component fields -->
</mat-form-field>
...

Resulting Form

image

Classes

Apply Method

ObjectBase.apply

Usage

new TextArea('comments', 'Comments').apply({
	// All the properties of the object you´re using "apply" method.
	singleLine: true, 
	validator: Validators.maxLength(100), 
	maxCharCount: 100 
}),

This method can be used in all classes of the lib (like kotlin apply).

🐳 Docker Support (for local development)

You can run this library in a Docker container to avoid dependency conflicts (e.g., Angular 11 with Node 14) and isolate it from other Angular projects.

🔧 Build Docker Image

Make sure you're in the root folder of the repo:

docker build -t angular11-dev -f Dockerfile .

If you don’t have a Dockerfile yet, you can create one like this:

# Usa Node.js 14, compatible con Angular 11
FROM node:14

# Establece el directorio de trabajo dentro del contenedor
WORKDIR /app

# Instala Angular CLI versión 11 de forma global
RUN npm install -g @angular/cli@11

# Copia los archivos de dependencias
COPY package*.json ./

# Instala las dependencias del proyecto
RUN npm install

# Copia el resto de archivos del proyecto
COPY . .

# Expone el puerto 4200 (Angular dev server)
EXPOSE 4200

# Comando por defecto (puede ser override en docker run)
CMD ["ng", "serve", "--host", "0.0.0.0"]

🚀 Run the Project in Docker

To serve the sandbox app locally (port 4200):

docker run -it --rm -v "$PWD":/app -w /app -p 4200:4200 --init angular11-dev ng serve --host 0.0.0.0

📦 Development Notes

  • Changes to your local source files will be reflected in the running Docker container automatically, because you're mounting the code with -v "$PWD":/app.
  • If you're using symlinks, make sure Git tracks them correctly (core.symlinks=true).
  • If other collaborators use the project, recommend them to run the symlink command once after cloning.

Package Sidebar

Install

npm i mat-dynamic-form

Weekly Downloads

6

Version

1.5.12

License

© 2020-2023 License, Carlos Ramos. All Rights Reserved.

Unpacked Size

1.72 MB

Total Files

58

Last publish

Collaborators

  • charlieras262