<!DOCTYPE html>
<html>

<head>
  <base href="." />
  <script type="text/javascript" charset="utf-8">
    window.AngularVersionForThisPlunker = 'latest'
  </script>
  <title>angular - By Advancesharp.com</title>
  <link rel="stylesheet" href="style.css" />
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
  <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
  
  <script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
  <script src="https://unpkg.com/zone.js/dist/zone.js"></script>
  <script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
  <script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
  <script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
  <script src="config.js"></script>
  <script>
    System.import('app')
      .catch(console.error.bind(console));
  </script>
</head>
<br>

<body class='container'>
  <h3>By <a href='http://www.advancesharp.com/blog/1214/angular-2-dynamically-add-remove-components'>Advancesharp.com</a> </h3>
  <my-app>
    loading...
  </my-app>
</body>

</html>

.row{
    margin-bottom: 10px;
}
input, button, .btn{border-radius: 0px  !important;}
input[type='text'].ng-invalid,
input[type='password'].ng-invalid,
input[type='email'].ng-invalid{border-left: 1px solid #700;}

input[type='text'].ng-valid,
input[type='password'].ng-valid,
input[type='email'].ng-valid{border-left: 1px solid #070;}

var angularVersion;
if(window.AngularVersionForThisPlunker === 'latest'){
  angularVersion = ''; //picks up latest
}
else {
  angularVersion = '@' + window.AngularVersionForThisPlunker;
}

System.config({
  //use typescript for compilation
  transpiler: 'typescript',
  //typescript compiler options
  typescriptOptions: {
    emitDecoratorMetadata: true
  },
  paths: {
    'npm:': 'https://unpkg.com/'
  },
  //map tells the System loader where to look for things
  map: {
    
    'app': './src',
    '@angular/core': 'npm:@angular/core'+ angularVersion + '/bundles/core.umd.js',
    '@angular/common': 'npm:@angular/common' + angularVersion + '/bundles/common.umd.js',
    '@angular/compiler': 'npm:@angular/compiler' + angularVersion  + '/bundles/compiler.umd.js',
    '@angular/platform-browser': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser.umd.js',
    '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic.umd.js',
    '@angular/http': 'npm:@angular/http' + angularVersion + '/bundles/http.umd.js',
    '@angular/router': 'npm:@angular/router' + angularVersion +'/bundles/router.umd.js',
    '@angular/forms': 'npm:@angular/forms' + angularVersion + '/bundles/forms.umd.js',
    '@angular/animations': 'npm:@angular/animations' + angularVersion + '/bundles/animations.umd.js',
    '@angular/platform-browser/animations': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-animations.umd.js',
    '@angular/animations/browser': 'npm:@angular/animations' + angularVersion + '/bundles/animations-browser.umd.js',
    
    '@angular/core/testing': 'npm:@angular/core' + angularVersion + '/bundles/core-testing.umd.js',
    '@angular/common/testing': 'npm:@angular/common' + angularVersion + '/bundles/common-testing.umd.js',
    '@angular/compiler/testing': 'npm:@angular/compiler' + angularVersion + '/bundles/compiler-testing.umd.js',
    '@angular/platform-browser/testing': 'npm:@angular/platform-browser' + angularVersion + '/bundles/platform-browser-testing.umd.js',
    '@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic' + angularVersion + '/bundles/platform-browser-dynamic-testing.umd.js',
    '@angular/http/testing': 'npm:@angular/http' + angularVersion + '/bundles/http-testing.umd.js',
    '@angular/router/testing': 'npm:@angular/router' + angularVersion + '/bundles/router-testing.umd.js',
    'tslib': 'npm:tslib@1.6.1',
    'rxjs': 'npm:rxjs',
    'typescript': 'npm:typescript@2.2.1/lib/typescript.js'
  },
  //packages defines our app package
  packages: {
    app: {
      main: './main.ts',
      defaultExtension: 'ts'
    },
    rxjs: {
      defaultExtension: 'js'
    }
  }
});
import {NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import {Router} from '@angular/router'

import { AppComponent } from './app/app.component';
import { EmailDirective } from './app/email.directive';
import { CompareDirective } from './app/compare.directive';

    
@NgModule({
  imports: [
    BrowserModule, FormsModule, ReactiveFormsModule
  ],
  declarations: [ AppComponent, EmailDirective, CompareDirective ],
  exports: [],
  bootstrap: [ AppComponent ]
})
export class AppModule {}

//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import { AppModule } from './app.module';


platformBrowserDynamic().bootstrapModule(AppModule)

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, EmailValidator } from '@angular/forms';


@Component({
  selector: 'my-app',
  templateUrl: './src/app/app.component.html'
})
export class AppComponent implements OnInit{ 
   register: FormGroup;
   isSubmitted: boolean = false;
   result: any = null;
   emailPattern: string = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
   
   constructor(private frmBuilder: FormBuilder) { }
   
   ngOnInit(){
     this.register = this.frmBuilder.group({
       name:["", [Validators.required, Validators.minLength(3),Validators.maxLength(15)]],
       email:["", [Validators.required, EmailValidator]],
       emailp:["", [Validators.required, Validators.pattern(this.emailPattern)]],
       emaild:["", [Validators.required]],
       password:["", [Validators.required]],
       verify:["", [Validators.required]]
     });
   }
   
   get name() { return this.register.get('name'); }
   get email() { return this.register.get('email'); }
   get emailp() { return this.register.get('emailp'); }
   get emaild() { return this.register.get('emaild'); }
   get password() { return this.register.get('password'); }
   get verify() { return this.register.get('verify'); }
  
   
   save(){
     this.isSubmitted = true;
     if(!this.register.valid)
         return;
     // Code to save the data
     // userService.Save(this.register.value);
     this.result = this.register.value;
      setTimeout(()=> {
       this.result = null;
       this.reset();
      }, 4000);
   }
   
   reset(){
     this.isSubmitted = false;
     this.register.reset();
     
   }
}


<h3>Registration</h3>
<hr />
<form [formGroup]='register' (ngSubmit)='save()' novalidate>
    <div class='row'>
      <div class='col-sm-6'>
        <input type='text' formControlName='name'
               class='form-control'
               placeholder='Display Name'>
        
      	<div *ngIf="name.invalid && (name.dirty || isSubmitted)" class="text-danger">
      	  <div *ngIf="name.errors.required">Name is required.</div>
      	  <div *ngIf="name.errors.minlength">
      		Name must be at least 4 characters long.
      	  </div>
      	  <div *ngIf="name.errors.maxlength">
      		Name must not exceed 15 characters.
      	  </div>
      	</div>
      </div>
    </div>
    
    <div class='row'>
      <div class='col-sm-6'>
        <input type='text' formControlName='email' email
               class='form-control'
               placeholder='Email builin validator'>
               
        <div *ngIf="email.invalid && (email.dirty || isSubmitted)" class="text-danger">
      		<div *ngIf="email.errors.required">Email is required.</div>
      		<div *ngIf="email.errors.email && !email.errors.required">Invalid email(build in).</div>
      	</div>
      </div>
    </div>
    
    
    <div class='row'>
      <div class='col-sm-6'>
        <input type='email' formControlName='emailp'
               class='form-control'
               placeholder='Email pattern validatior'>
               
        <div *ngIf="emailp.invalid && (emailp.dirty || isSubmitted)" class="text-danger">
      		<div *ngIf="emailp.errors.required">Email is required.</div>
      		<div *ngIf="emailp.errors.pattern && !emailp.errors.required">Invalid email(from pattern).</div>
      	</div>
      </div>
    </div>
    
    
    <div class='row'>
      <div class='col-sm-6'>
        <input type='text' formControlName='emaild'
               class='form-control' advs-email
               placeholder='Email directive validatior'>
               
        <div *ngIf="emaild.invalid && (emaild.dirty || isSubmitted)" class="text-danger">
      			<div *ngIf="emaild.errors.required">Email is required.</div>
      		  <div *ngIf="emaild.errors.pattern && !emaild.errors.required">Invalid email( from directive).</div>
      	</div>
      </div>
    </div>
    
    <div class='row'>
      <div class='col-sm-6'>
        <input type='password' formControlName='password'
               class='form-control' 
               advs-compare="verify" parent='true'
               placeholder='Password'>
               
        <div *ngIf="password.invalid && (password.dirty || isSubmitted)" class="text-danger">
      		Password is required.
      	</div>
      </div>
    </div>
    
    
    <div class='row'>
      <div class='col-sm-6'>
        <input type='password' formControlName='verify'
               class='form-control'
               advs-compare="password" parent='false'
               placeholder='Verify Password'>
             
        <div *ngIf="verify.invalid && (verify.dirty || isSubmitted)" class="text-danger">
      		<div *ngIf="verify.errors.required">Verify Password is required.</div>
      		<div *ngIf="verify.errors.compare && !verify.errors.required">Password Mismatch.</div>
      	</div>
      </div>
    </div>
    
    <div class='row'>
      <div class='col-sm-6'>
        <button type='submit' class='btn btn-primary'>Save</button>
        <button type='button' class='btn btn-warning' (click)='reset()'>Reset</button>
      </div>
    </div>
</form>

<pre *ngIf='result != null'>
  {{result | json}}
</pre>




import { Directive, Attribute  } from '@angular/core';
import { Validator,  NG_VALIDATORS } from '@angular/forms';


@Directive({
  selector: '[advs-compare]',
  providers: [{provide: NG_VALIDATORS, useExisting: CompareDirective, multi: true}]
})
export class CompareDirective implements Validator {
  
  constructor(@Attribute('advs-compare') public comparer: string,
              @Attribute('parent') public parent: string){}
  
  validate(c: Control): {[key: string]: any} {
    let e = c.root.get(this.comparer);
    
    
    // value not equal in verify control
    if (e && c.value !== e.value && !this.isParent) {
      return {"compare": true};
    }
    
    // user typing in password and match
    if (e && c.value === e.value && this.isParent) {
        delete e.errors['compare'];
        if (!Object.keys(e.errors).length) e.setErrors(null);
    }
    
    // user typing in password and mis-match
    if (e && c.value !== e.value && this.isParent) {
        e.setErrors({ "compare": true });
    }
  }
  
  private get isParent() {
    if (!this.parent) 
      return false;
         
    return this.parent === 'true' ? true: false;
  }
}
import { Directive } from '@angular/core';
import { Validator,  NG_VALIDATORS } from '@angular/forms';


@Directive({
  selector: '[advs-email]',
  providers: [{provide: NG_VALIDATORS, useExisting: EmailDirective, multi: true}]
})
export class EmailDirective implements Validator {
  emailPattern: string = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
  
  validate(c: Control): {[key: string]: any} {
    if(c.value == null)
      return null;
   
    if(!this.emailPattern.test(c.value)){
      return {"pattern": true};
    }
    return null;
  }
}