Saturday, January 5, 2019

Reactive FormGroup validation with AbstractControl in Angular 2 ?

Validation in Angular (v2+), various approaches, various APIs to use. We’re going to use AbstractControl to learn how to validate a particular FormGroup. I covered FormGroup, FormControl and FormBuilder in my previous reactives form fundamentals article - which I’d recommend checking out before this one if you’re new to Angular forms.

What is a FormGroup?

Covered in the previous article, but we’ll whip up a quick sample real quick to use for the rest of this post:
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { User } from './signup.interface';

@Component({...})
export class SignupFormComponent implements OnInit {
  user: FormGroup;
  constructor(private fb: FormBuilder) {}
  ngOnInit() {
    this.user = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(2)]],
      account: this.fb.group({
        email: ['', Validators.required],
        confirm: ['', Validators.required]
      })
    });
  }
  onSubmit({ value, valid }: { value: User, valid: boolean }) {
    console.log(value, valid);
  }
}
If the above makes no sense, go here then drop back! When our FormBuilder, i.e. the fb injected FormBuilder instantiates new groups through this.fb.group(), each of those is technically a new FormGroup(). So when we refer to “FormGroups”, this is what we’re talking about from here on out.

FormBuilder/FormGroup source code

Before we can learn “how to do custom validation”, we must dive into the workings of the APIs first to see what’s happening and actually have some idea what’s going on, so let’s do that real quick. Here’s the syntax for the FormBuilder class:
class FormBuilder {
  group(controlsConfig: {[key: string]: any}, extra?: {[key: string]: any}) : FormGroup
  control(formState: Object, validator?: ValidatorFn|ValidatorFn[], asyncValidator?: AsyncValidatorFn|AsyncValidatorFn[]) : FormControl
  array(controlsConfig: any[], validator?: ValidatorFn, asyncValidator?: AsyncValidatorFn) : FormArray
}
First, let’s look at this line:
group(controlsConfig: {[key: string]: any}, extra?: {[key: string]: any}) : FormGroup
This means we can pass a controlsConfig Object down into the FormBuilder. This is what happens when we call this.fb.group(). We also have an optional extra? property, and finally : FormGroup, which is the return value. So essentially, FormBuilder is just an abstraction/wrapper at this point.
So, what do the internals look like?
group(controlsConfig: {[key: string]: any}, extra: {[key: string]: any} = null): FormGroup {
  const controls = this._reduceControls(controlsConfig);
  const validator: ValidatorFn = isPresent(extra) ? extra['validator'] : null;
  const asyncValidator: AsyncValidatorFn = isPresent(extra) ? extra['asyncValidator'] : null;
  return new FormGroup(controls, validator, asyncValidator);
}
The first line of code we completely know already, it’s just the syntax from above. Now, what is this extra argument that’s being passed in? Here’s where it’s used:
const validator: ValidatorFn = isPresent(extra) ? extra['validator'] : null;
Interesting, it checks the presence of the extra “thing”, and providing it’s there and is in fact an Object, it’ll grab the validator property from it. Which means that the extra thing which is the optional second function argument, in fact looks like this when creating a group() with FormBuilder:
this.fb.group({...}, { validator: someCustomValidator })
Which is equivalent to:
new FormGroup({...}, someCustomValidator)
We can pass a second argument (or third, for asyncValidator) that gets passed to new FormGroup() instance. One more thing before we implement validation, we’ll see how FormGroup handles this internally:
export class FormGroup extends AbstractControl {
  constructor(
      public controls: {[key: string]: AbstractControl},
      validator: ValidatorFn = null,
      asyncValidator: AsyncValidatorFn = null
    ) {
    super(validator, asyncValidator);
    this._initObservables();
    this._setUpControls();
    this.updateValueAndValidity({onlySelf: true, emitEvent: false});
  }
  //...
}
FormGroup actually extends AbstractControl and then passes validator and asyncValidator to the AbstractControl through the super() call, which calls the constructor of the parent abstract class.
We won’t dive into the specifics of AbstractControl, but we know that it’s essentially the mothership of our form that sets, controls, and powers all things such as dirty, pristine, touched and other funky abstract methods we can touch when we ask the AbstractControl.

AbstractControl

This next section will give you an insight on AbstractControl, however using AbstractControl is not essential in this case to implementing our custom FormGroup validation, as we can also inject FormGroup to talk to our form controls also - but this means the “control” that’s injected needs to be a FormGroup instance, so we can use AbstractControl instead for consistency.
Let’s circle back around and take a look at our original piece of code:
@Component({...})
export class SignupFormComponent implements OnInit {
  user: FormGroup;
  constructor(private fb: FormBuilder) {}
  ngOnInit() {
    this.user = this.fb.group({
      name: ['', [Validators.required, Validators.minLength(2)]],
      account: this.fb.group({
        email: ['', Validators.required],
        confirm: ['', Validators.required]
      })
    });
  }
}
What we’re going to add is a custom validator that ensures when our lovely fake users sign up to our fake form, that their email and confirm email fields both match up. Using AbstractControl we can do this, but first, we need to actually compose the validation function:
// email-matcher.ts
export const emailMatcher = () => {};
We’ll add this inside email-matcher.ts for the sake of breaking code up into different files. This will allow us to then inject it into our emailMatcher validator into our FormGroup or FormBuilder wrapper.
Next step, we’ll inject AbstractControl:
export const emailMatcher = (control: AbstractControl): {[key: string]: boolean} => {

};
So, we know now that AbstractControl is the mothership of our form that other form controls simply extend/inherit from, which means we can actually talk to any form control in the group. If you recall from the previous article, we can fetch information about our form controls via .get(<control>) to implement client-side validation errors, for example:
<div class="error" *ngIf="user.get('foo').touched && user.get('foo').hasError('required')">
  This field is required
</div>
Incidentally, we can also use this same API when implementing custom validators, so referencing our previous form group code, in which we have nested FormGroup props email and confirm, let’s go grab them:
export const emailMatcher = (control: AbstractControl): {[key: string]: boolean} => {
  const email = control.get('email');
  const confirm = control.get('confirm');
};
At this point, control is FormGroup. Our email and confirm are both FormControl, if we logged them out in the console we’d see this:
 FormGroup {asyncValidator: null, _pristine: true, _touched: false, _onDisabledChange: Array[0], controls: Object}
 FormControl {asyncValidator: null, _pristine: true, _touched: false, _onDisabledChange: Array[1], _onChange: Array[1]}
 FormControl {asyncValidator: null, _pristine: true, _touched: false, _onDisabledChange: Array[1], _onChange: Array[1]}

Custom validation properties

Now we’re ready to do some fun stuff! All we actually want to do is compare that both the email and confirm fields have the same value, which will in turn display errors if they are invalid. Let’s check the .value property (the actual FormControl value, i.e. the <input>) and if they match we’ll return null (which internally sets the validation state for the entire group, and entire form where applicable):
export const emailMatcher = (control: AbstractControl): {[key: string]: boolean} => {
  const email = control.get('email');
  const confirm = control.get('confirm');
  if (!email || !confirm) return null;
  if (email.value === confirm.value) {
    return null;
  }
};
So until now, this means that if everything is working perfectly, we’ll return no errors. Now we need to add that custom validation.

Custom validation Object hook

What we want to implement is the validation that matches this HTML:
...
  <div formGroupName="account">
    <label>
      <span>Email address</span>
      <input type="email" placeholder="Your email address" formControlName="email">
    </label>
    <label>
      <span>Confirm address</span>
      <input type="email" placeholder="Confirm your email address" formControlName="confirm">
    </label>
    <div class="error" *ngIf="user.get('account').touched && user.get('account').hasError('nomatch')">
      Email addresses must match
    </div>
  </div>
...
Ignoring the HTML, we’re interested specifically in this piece:
user.get('account').hasError('nomatch')
This means that we want to be able to query the account level FormGroup, and check if it has an error called “nomatch”. To implement this we require a custom Object to be returned from our validator should the values not match:
export const emailMatcher = (control: AbstractControl): {[key: string]: boolean} => {
  ...
  if (email.value === confirm.value) {
    return null;
  } else {
    return { nomatch: true };
  }
};
We can condense this nicely onto a one line ternary, final code:
export const emailMatcher = (control: AbstractControl): {[key: string]: boolean} => {
  const email = control.get('email');
  const confirm = control.get('confirm');
  if (!email || !confirm) return null;
  return email.value === confirm.value ? null : { nomatch: true };
};
Now, we import our validator, and add it to the second argument of the account level FormGroup:
...
import { emailMatcher } from './email-matcher';
...
  ngOnInit() {
    this.user = this.fb.group({
      name: ['', Validators.required],
      account: this.fb.group({
        email: ['', Validators.required],
        confirm: ['', Validators.required]
      }, { validator: emailMatcher })
    });
  }
...

Why use AbstractFormControl Example?

Answer : AbstractFormControl is abstract class that is used for custom form Control 
and validation. Example :

emailDomain(domainName: string) {
return (params: AbstractControl): { [key: string]: any } | null => {
const email: string = params.value;
const domain = email.substring(email.lastIndexOf('@' + 1));
if (email === '' || domain.toLowerCase() === domainName.toLowerCase()) {
return null;
} else {
return { 'emailDomain': true };



}
};

Disable validation of HTML5 form elements

<form method="post" action="/foo" novalidate>...</form>

What is the maximum length of a valid email address?

An email address must not exceed 254 characters.
The maximum length specified in RFC 5321 states:

When to use FormGroup vs. FormArray?


FormGroup:
A FormGroup aggregates the values of each child FormControl into one object, with each control name as the key.
const form = new FormGroup({
  first: new FormControl('Nancy', Validators.minLength(2)),
  last: new FormControl('Drew'),
});
FormArray:
A FormArray aggregates the values of each child FormControl into an array.
const arr = new FormArray([
  new FormControl('Nancy', Validators.minLength(2)),
  new FormControl('Drew'),
]);

Answer :
FormArray is a variant of FormGroup. The key difference is that its data gets serialized as an array (as opposed to being serialized as an object in case of FormGroup). This might be especially useful when you don’t know how many controls will be present within the group, like dynamic forms.

Friday, January 4, 2019

Difference between angular 2 and angular 6?

Points are :-

1.) Bundle size in angular 6 is reduced and load time of application is also improved.
2.) And angular 2 have typescript 2.1 support and angular 6 have latest typescript 2.7+
3.) Angular 2 Don't have support of native element and angular 6 comes with added to support of native element.
4.)  The HttpModule has been replaced by the HttpClientModule, which is easier to use and has a few more features.
5.) The biggest changes are probably the router and the HTTP-coomunication.
6.) ng update <package> is a new CLI command that analyzes your package.json.
7.)Another new CLI command ng add <package> makes adding new capabilities to your project easy. ng add will use your package manager to download new dependencies and invoke an installation script.
8.)The biggest addition is the new tree component for displaying hierarchical data. These new tree components come in both styled (Material’s mat-tree) and unstyled versions (CDK’s cdk-tree).Alongside the tree, we also have new badge and bottom-sheet components.
9.) Angular has been updated to use v6 of RxJS.
10.) Animation Performance Improvement by removing web annimaion-pollyfill.
11.) To make your applications smaller, we’ve moved from modules referencing services to services referencing modules. This allows us to only bundle services into your code base in modules where they are injected.No references are needed in our NgModule.
12.) Creating and Building Library Support.
13.)CLI-V6 now supported.
9.) 

48 answers on StackOverflow to the most popular Angular questions I gathered the most common questions and answers from Stac...