Showing posts with label Angular 5. Show all posts
Showing posts with label Angular 5. Show all posts

Friday, March 30, 2018

Added a generateForm() Method to vadacl

Today I published a new version of my vadacl library that includes a new convenience method:  generateForm().  The generateForm() method accepts a data object and returns a FormGroup with FormControl instances generated from the properties and any vadacl-based validation configurations associated with the data object.

So instead of declaring the FormGroup and FormControl instances manually:

export class CruiseShipComponent extends Vadacl implements OnInit {
  cruiseShip: CruiseShip;
  shipForm: FormGroup;

  ngOnInit() {
    this.cruiseShip = new CruiseShip();
    this.shipForm = new FormGroup({
      'name': new FormControl( this.cruiseShip.name, this.applyRules( this.cruiseShip, 'name' ) ),
      'cruiseLine': new FormControl( this.cruiseShip.cruiseLine, this.applyRules( this.cruiseShip, 'cruiseLine' ) ),
      'yearBuilt': new FormControl( this.cruiseShip.yearBuilt, this.applyRules( this.cruiseShip, 'yearBuilt' ) )
    });
  }

...you can simply invoke generateForm() with the data object:

...
ngOnInit() {
  this.cruiseShip = new CruiseShip();
  this.shipForm = this.generateForm( this.cruiseShip );
}

generateForm() also accepts a second arguments:  a "mods" object that allows you to customize the FormGroup returned by the method.  The possible modification properties are:
  • exclude:  an array of data object properties you don't want to create a FormControl for.
  • only:  an array of the only data object properties you want to create FormControls for (overrides the "exclude" property if you mistakenly use both).
  • rename: an object literal for remapping a data object property name (key) to a different FormControl name (value).
  • validations: an object literal of additional validations to apply to particular data object properties.

An example of using the mods argument:
this.shipForm = this.generateForm( this.cruiseShip, {
  exclude: [ 'yearBuilt' ],
  rename: { cruiseLine: 'company' },
  validations: {
     name: { maxLength: { maxLength: 100, message: 'Ship name cannot be longer than 100 characters' } }
  }
});

The Angular application I maintain on GitHub to demonstrate vadacl has been updated with a demo that uses generateForm(). 

Thursday, December 28, 2017

Angular Update Guide:

Earlier today when I wanted to retest my vadacl library against the latest version of Angular (5.1.2), I skimmed through the Angular blog post regarding the 5.0 release, and at the bottom of the post was a mention of a new upgrade tool:  the Angular Update Guide.



The guide is a Firebase-backed Angular web application styled with Angular Material.  You enter the Angular version you're currently running, the version you want to upgrade to, answer some general questions and press the button.  What you get is a set of brief (at least in my case) instructions for how to perform the upgrade, and what kind of changes you may need to make to your code before and after the update.

I'm glad the Angular team made this tool.  Updating the semver version of the Angular packages in the package.json file is usually simple:  it's knowing what the versions of other dependencies like rxjs or TypeScript need to be in order to make it work that's trickier.  And this takes care of that.

Inadvertent Example of the Benefit of vadacl's Class-Based Validation Rules

While I was verifying that my vadacl validation library wasn't adversely affected ("broken") by any changes in the latest version of Angular (5.1.2), I discovered that one of my validations wasn't working correctly.

In two of the forms in the vadacl demo I have up on GitHub, there is a "Gender" form field where the user is only allowed to enter "M" or "F".  As I was testing the validation on that field, I was surprised to see that while the "F" validation was being enforced, the "M" validation was allowing any word that started with the letter "M".

The validation rule was defined within the UserProfile object class in the demo:  one of the main features of vadacl is that you can define your validations in a class, like so...
validations: { [ index: string ] : PropertyValidations } = {
    firstName: {
      maxLength: { maxLength: 25 },
      required: {}
    },
    lastName: {
      maxLength: { maxLength: 25, message: 'Your last name cannot be longer than 25 characters.'},
      required: { message: 'Your last name is required.' }
    },
    username: {
      maxLength: { maxLength: 30, message: 'Your username cannot be longer than 30 characters.'},
      required: { message: 'You must have a username.' }
    },
    password: {
      minLength: { minLength: 6, message: 'Your password must be at least 6 characters long.' },
      required: { message: 'You must provide a password.' },
    },
    age: {
      pattern: { pattern: '[0-9]*', message: 'Enter your age as an integer.' }
    },
    gender: {
      pattern: { pattern: 'M|F', message: 'Enter your gender as "M" or "F".' }
    }
};

...and then utilize them in your components. The rule invoked the Pattern Validator method using the following pattern:

M|F

I thought that the either/or pipe would limit the valid value to either "M" or "F", but apparently not, and by virtue of being in front of the pipe the male validation allowed for characters beyond the "M".  So I fixed the validation by changing the pattern to:

[MF]{1}

If this same issue had come up in a different application that used normal Angular reactive form validation, I would have had to correct the pattern in the form controls in both of the components, rather than just once.