# Lysis Angular form validator generator

## Overview

This generator creates Angular validators from the backend, to ease forms creation.

## Basic usage

### The controller

In a controller, to validate form input for books:

```
import { Component, OnInit } from '@angular/core';

import { BooksService } from '../backend/services';
import { Book } from '../backend/classes';
import { FormService, Form } from '../backend/forms';

@Component({
  selector: 'app-books-list',
  templateUrl: './books-list.component.html',
  styleUrls: ['./books-list.component.css']
})

export class BooksListComponent implements OnInit {
  books: Array<Book> = [];
  form: Form<Book>;

  constructor(
    private booksService : BooksService,
    formService: FormService
  ) {}

  ngOnInit() {
    this.booksService.getAll().subscribe(books => {
      this.books = books;
    });
    // initialize the form with a whole new book
    this.createNewBook();
  }

  createNewBook(): void {
    this.form = this.formService.makeForm<Book>(new Book());
  }

  // used in the template, for example in a data table
  selectBook(book: Book): void {
    this.form = this.formService.makeForm<Book>(book);
  }

  // create or update the book
  commitBook(): void {
    if (this.form.group.dirty && this.form.group.valid) {
      var newBook = this.form.get();
      if (newBook.id) {
        this.booksService.update(newBook).subscribe(book => console.log('yeah!'));
      } else {
        this.booksService.add(newBook).subscribe(book => console.log('yeah!'));
      }
    } else {
      // force invalid inputs state to display errors
      this.form.displayErrors();
    }
  }
}
```

Note: it works well with services generated by [Lysis Restangular services generator](https://github.com/momenttech/lysis-restangular-services-generator) and classes from [Lysis TypeScript classes generator ](https://github.com/momenttech/lysis-typescript-classes-generator).

### The template

The associated template takes advantage of Angular form groups to display values in form fields and to handle validation:

```
<form [formGroup]="form.group" (submit)="commitBook()">
  <input type="text" placeholder="Title" formControlName="title">
  <textarea placeholder="Description" formControlName="description"></textarea>
  <input type="date" placeholder="Publication date" formControlName="publicationDate">
  [...]
  <button>Apply</button>
</form>
```

## Use

### Prerequisites

If it is not already done, install api-lysis globally and as dev dependency:

```
npm install api-lysis -g
npm install api-lysis --save-dev
```

### Install this generator

Install this generator:

```
npm install lysis-angular-form-validators-generator --save-dev
```

### Configuration

Configuration sample:

```
apis:
  http://localhost:8000:
    basePath: 'my-backend'
    hydraPrefix: 'hydra:'
    generators:
      lysis-angular-form-validators-generator:
        dir: 'forms'
        classPath: '../classes'
```

Services files are generated in `my-backend/forms`.

If `dir` is not set, the default value is `form-validators`.

`classPath` is the path to class files. By default it is set to `../backend-classes`.


### Add modules and services

As the form service provided by this generator uses Angular reactive forms and ng2-validation, it must be installed:

    npm install ng2-validation --save

It should be enabled in `app.module.ts`, as well as `FormService`:

```
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FormService } from './my-backend/form-validators';
[...]
@NgModule({
  imports: [
    [...]
    ReactiveFormsModule,
    [...]
  ],
  providers: [
    [...]
    FormService,
    [...]
  ]
})
```

### Start Lysis

Start Lysis, without writing files:

    lysis --dry-run

Start Lysis:

    lysis

## Customize form validators

A validators set is created for each resource.

Example of validators set to check books, in the generated file `BookValidatorsBase.ts`:

```
export class BookValidatorsBase extends FormGroupValidators {
    id = [CustomValidators.digits];
    isbn = null;
    description = [Validators.required];
    author = [Validators.required];
    title = [Validators.required];
    publicationDate = [Validators.required, CustomValidators.date];
}
```

[Built-in validators](https://angular.io/api/forms/Validators) and validators from [ng2-validation](https://www.npmjs.com/package/ng2-validation).

This file is updated each time you start Lysis, then it should not be modified.

### Customize property validators

For example, to change `author` max length, edit the `BookValidators.ts` file:

```
export class BookValidators extends BookValidatorsBase {
  author = [Validators.required, Validators.maxLength(10)];
}
```

Here, only `author` validators are changed. Other validators are kept unchanged.

### Add your own property validators (aka app validators)

If you need to create your own validators, such as `postalCode` or `isbn` validators, add new files in `app-validators` and register it in `app-validators/index.ts`.

To use it, import `AppValidators`, for example in property validators files:

```
import { AppValidators } from '../backend/forms';
```

### Item type/validator matcher

Todo

### Instantiate a new form validator manually

The form service automatically provides a form with the matching validator according to the provided item.

If you need to create a form from another class or validator, do not use the `FormService` and instantiate it manually providing base class and validator:

```
import { FormBuilder } from '@angular/forms';
import { Form } from './Form';

[...]
this.form = new Form<CustomBook>(this.formBuilder, customBook, {itemClass: CustomBook, validator: customBookValidator});
```
