angular-cn/aio/content/examples/cb-form-validation/ts/plnkr.no-link.html

768 lines
25 KiB
HTML
Raw Normal View History

<html lang="en"><head></head><body><form id="mainForm" method="post" action="http://plnkr.co/edit/?p=preview" target="_self"><input type="hidden" name="files[app/app.component.ts]" value="import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `<hero-form-template1></hero-form-template1>
<hr>
<hero-form-template2></hero-form-template2>
<hr>
<hero-form-reactive3></hero-form-reactive3>`
})
export class AppComponent { }
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/app.module.ts]" value="import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { HeroFormTemplateModule } from './template/hero-form-template.module';
import { HeroFormReactiveModule } from './reactive/hero-form-reactive.module';
@NgModule({
imports: [
BrowserModule,
HeroFormTemplateModule,
HeroFormReactiveModule
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/reactive/hero-form-reactive.component.ts]" value="/* tslint:disable: member-ordering forin */
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { Hero } from '../shared/hero';
import { forbiddenNameValidator } from '../shared/forbidden-name.directive';
@Component({
moduleId: module.id,
selector: 'hero-form-reactive3',
templateUrl: './hero-form-reactive.component.html'
})
export class HeroFormReactiveComponent implements OnInit {
powers = ['Really Smart', 'Super Flexible', 'Weather Changer'];
hero = new Hero(18, 'Dr. WhatIsHisName', this.powers[0], 'Dr. What');
submitted = false;
onSubmit() {
this.submitted = true;
this.hero = this.heroForm.value;
}
// Reset the form with a new hero AND restore 'pristine' class state
// by toggling 'active' flag which causes the form
// to be removed/re-added in a tick via NgIf
// TODO: Workaround until NgForm has a reset method (#6822)
active = true;
addHero() {
this.hero = new Hero(42, '', '');
this.buildForm();
this.active = false;
setTimeout(() => this.active = true, 0);
}
heroForm: FormGroup;
constructor(private fb: FormBuilder) { }
ngOnInit(): void {
this.buildForm();
}
buildForm(): void {
this.heroForm = this.fb.group({
'name': [this.hero.name, [
Validators.required,
Validators.minLength(4),
Validators.maxLength(24),
forbiddenNameValidator(/bob/i)
]
],
'alterEgo': [this.hero.alterEgo],
'power': [this.hero.power, Validators.required]
});
this.heroForm.valueChanges
.subscribe(data => this.onValueChanged(data));
this.onValueChanged(); // (re)set validation messages now
}
onValueChanged(data?: any) {
if (!this.heroForm) { return; }
const form = this.heroForm;
for (const field in this.formErrors) {
// clear previous error message (if any)
this.formErrors[field] = '';
const control = form.get(field);
if (control &amp;&amp; control.dirty &amp;&amp; !control.valid) {
const messages = this.validationMessages[field];
for (const key in control.errors) {
this.formErrors[field] += messages[key] + ' ';
}
}
}
}
formErrors = {
'name': '',
'power': ''
};
validationMessages = {
'name': {
'required': 'Name is required.',
'minlength': 'Name must be at least 4 characters long.',
'maxlength': 'Name cannot be more than 24 characters long.',
'forbiddenName': 'Someone named &quot;Bob&quot; cannot be a hero.'
},
'power': {
'required': 'Power is required.'
}
};
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/reactive/hero-form-reactive.module.ts]" value="import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { SharedModule } from '../shared/shared.module';
import { HeroFormReactiveComponent } from './hero-form-reactive.component';
@NgModule({
imports: [ SharedModule, ReactiveFormsModule ],
declarations: [ HeroFormReactiveComponent ],
exports: [ HeroFormReactiveComponent ]
})
export class HeroFormReactiveModule { }
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/shared/forbidden-name.directive.ts]" value="import { Directive, Input, OnChanges, SimpleChanges } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, Validator, ValidatorFn, Validators } from '@angular/forms';
/** A hero's name can't match the given regular expression */
export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
return (control: AbstractControl): {[key: string]: any} => {
const name = control.value;
const no = nameRe.test(name);
return no ? {'forbiddenName': {name}} : null;
};
}
@Directive({
selector: '[forbiddenName]',
providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}]
})
export class ForbiddenValidatorDirective implements Validator, OnChanges {
@Input() forbiddenName: string;
private valFn = Validators.nullValidator;
ngOnChanges(changes: SimpleChanges): void {
const change = changes['forbiddenName'];
if (change) {
const val: string | RegExp = change.currentValue;
const re = val instanceof RegExp ? val : new RegExp(val, 'i');
this.valFn = forbiddenNameValidator(re);
} else {
this.valFn = Validators.nullValidator;
}
}
validate(control: AbstractControl): {[key: string]: any} {
return this.valFn(control);
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/shared/hero.ts]" value="export class Hero {
constructor(
public id: number,
public name: string,
public power: string,
public alterEgo?: string
) { }
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/shared/shared.module.ts]" value="import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ForbiddenValidatorDirective } from './forbidden-name.directive';
import { SubmittedComponent } from './submitted.component';
@NgModule({
imports: [ CommonModule],
declarations: [ ForbiddenValidatorDirective, SubmittedComponent ],
exports: [ ForbiddenValidatorDirective, SubmittedComponent,
CommonModule ]
})
export class SharedModule { }
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/shared/submitted.component.ts]" value="import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Hero } from './hero';
@Component({
selector: 'hero-submitted',
template: `
<div *ngIf=&quot;submitted&quot;>
<h2>You submitted the following:</h2>
<div class=&quot;row&quot;>
<div class=&quot;col-xs-3&quot;>Name</div>
<div class=&quot;col-xs-9 pull-left&quot;>{{ hero.name }}</div>
</div>
<div class=&quot;row&quot;>
<div class=&quot;col-xs-3&quot;>Alter Ego</div>
<div class=&quot;col-xs-9 pull-left&quot;>{{ hero.alterEgo }}</div>
</div>
<div class=&quot;row&quot;>
<div class=&quot;col-xs-3&quot;>Power</div>
<div class=&quot;col-xs-9 pull-left&quot;>{{ hero.power }}</div>
</div>
<br>
<button class=&quot;btn btn-default&quot; (click)=&quot;onClick()&quot;>Edit</button>
</div>`
})
export class SubmittedComponent {
@Input() hero: Hero;
@Input() submitted = false;
@Output() submittedChange = new EventEmitter<boolean>();
onClick() { this.submittedChange.emit(false); }
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/template/hero-form-template.module.ts]" value="import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { SharedModule } from '../shared/shared.module';
import { HeroFormTemplate1Component } from './hero-form-template1.component';
import { HeroFormTemplate2Component } from './hero-form-template2.component';
@NgModule({
imports: [ SharedModule, FormsModule ],
declarations: [ HeroFormTemplate1Component, HeroFormTemplate2Component ],
exports: [ HeroFormTemplate1Component, HeroFormTemplate2Component ]
})
export class HeroFormTemplateModule { }
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/template/hero-form-template1.component.ts]" value="/* tslint:disable: member-ordering */
import { Component } from '@angular/core';
import { Hero } from '../shared/hero';
@Component({
moduleId: module.id,
selector: 'hero-form-template1',
templateUrl: './hero-form-template1.component.html'
})
export class HeroFormTemplate1Component {
powers = ['Really Smart', 'Super Flexible', 'Weather Changer'];
hero = new Hero(18, 'Dr. WhatIsHisWayTooLongName', this.powers[0], 'Dr. What');
submitted = false;
onSubmit() {
this.submitted = true;
}
// Reset the form with a new hero AND restore 'pristine' class state
// by toggling 'active' flag which causes the form
// to be removed/re-added in a tick via NgIf
// TODO: Workaround until NgForm has a reset method (#6822)
active = true;
addHero() {
this.hero = new Hero(42, '', '');
this.active = false;
setTimeout(() => this.active = true, 0);
}
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/template/hero-form-template2.component.ts]" value="/* tslint:disable: member-ordering forin */
import { Component, AfterViewChecked, ViewChild } from '@angular/core';
import { NgForm } from '@angular/forms';
import { Hero } from '../shared/hero';
@Component({
moduleId: module.id,
selector: 'hero-form-template2',
templateUrl: './hero-form-template2.component.html'
})
export class HeroFormTemplate2Component implements AfterViewChecked {
powers = ['Really Smart', 'Super Flexible', 'Weather Changer'];
hero = new Hero(18, 'Dr. WhatIsHisWayTooLongName', this.powers[0], 'Dr. What');
submitted = false;
onSubmit() {
this.submitted = true;
}
// Reset the form with a new hero AND restore 'pristine' class state
// by toggling 'active' flag which causes the form
// to be removed/re-added in a tick via NgIf
// TODO: Workaround until NgForm has a reset method (#6822)
active = true;
addHero() {
this.hero = new Hero(42, '', '');
this.active = false;
setTimeout(() => this.active = true, 0);
}
heroForm: NgForm;
@ViewChild('heroForm') currentForm: NgForm;
ngAfterViewChecked() {
this.formChanged();
}
formChanged() {
if (this.currentForm === this.heroForm) { return; }
this.heroForm = this.currentForm;
if (this.heroForm) {
this.heroForm.valueChanges
.subscribe(data => this.onValueChanged(data));
}
}
onValueChanged(data?: any) {
if (!this.heroForm) { return; }
const form = this.heroForm.form;
for (const field in this.formErrors) {
// clear previous error message (if any)
this.formErrors[field] = '';
const control = form.get(field);
if (control &amp;&amp; control.dirty &amp;&amp; !control.valid) {
const messages = this.validationMessages[field];
for (const key in control.errors) {
this.formErrors[field] += messages[key] + ' ';
}
}
}
}
formErrors = {
'name': '',
'power': ''
};
validationMessages = {
'name': {
'required': 'Name is required.',
'minlength': 'Name must be at least 4 characters long.',
'maxlength': 'Name cannot be more than 24 characters long.',
'forbiddenName': 'Someone named &quot;Bob&quot; cannot be a hero.'
},
'power': {
'required': 'Power is required.'
}
};
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[main.ts]" value="import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[forms.css]" value=".ng-valid[required], .ng-valid.required {
border-left: 5px solid #42A948; /* green */
}
.ng-invalid:not(form) {
border-left: 5px solid #a94442; /* red */
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[styles.css]" value="/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
body, input[text], button {
color: #888;
font-family: Cambria, Georgia;
}
a {
cursor: pointer;
cursor: hand;
}
button {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;
}
button:disabled {
background-color: #eee;
color: #aaa;
cursor: auto;
}
/* Navigation link styles */
nav a {
padding: 5px 10px;
text-decoration: none;
margin-right: 10px;
margin-top: 10px;
display: inline-block;
background-color: #eee;
border-radius: 4px;
}
nav a:visited, a:link {
color: #607D8B;
}
nav a:hover {
color: #039be5;
background-color: #CFD8DC;
}
nav a.active {
color: #039be5;
}
/* items class */
.items {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 24em;
}
.items li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0;
height: 1.6em;
border-radius: 4px;
}
.items li:hover {
color: #607D8B;
background-color: #DDD;
left: .1em;
}
.items li.selected {
background-color: #CFD8DC;
color: white;
}
.items li.selected:hover {
background-color: #BBD8DC;
}
.items .text {
position: relative;
top: -3px;
}
.items .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
/* everywhere else */
* {
font-family: Arial, Helvetica, sans-serif;
}
/*
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/"><input type="hidden" name="files[app/reactive/hero-form-reactive.component.html]" value="<div class=&quot;container&quot;>
<div [hidden]=&quot;submitted&quot;>
<h1>Hero Form 3 (Reactive)</h1>
<form [formGroup]=&quot;heroForm&quot; *ngIf=&quot;active&quot; (ngSubmit)=&quot;onSubmit()&quot;>
<div class=&quot;form-group&quot;>
<label for=&quot;name&quot;>Name</label>
<input type=&quot;text&quot; id=&quot;name&quot; class=&quot;form-control&quot;
formControlName=&quot;name&quot; required >
<div *ngIf=&quot;formErrors.name&quot; class=&quot;alert alert-danger&quot;>
{{ formErrors.name }}
</div>
</div>
<div class=&quot;form-group&quot;>
<label for=&quot;alterEgo&quot;>Alter Ego</label>
<input type=&quot;text&quot; id=&quot;alterEgo&quot; class=&quot;form-control&quot;
formControlName=&quot;alterEgo&quot; >
</div>
<div class=&quot;form-group&quot;>
<label for=&quot;power&quot;>Hero Power</label>
<select id=&quot;power&quot; class=&quot;form-control&quot;
formControlName=&quot;power&quot; required >
<option *ngFor=&quot;let p of powers&quot; [value]=&quot;p&quot;>{{p}}</option>
</select>
<div *ngIf=&quot;formErrors.power&quot; class=&quot;alert alert-danger&quot;>
{{ formErrors.power }}
</div>
</div>
<button type=&quot;submit&quot; class=&quot;btn btn-default&quot;
[disabled]=&quot;!heroForm.valid&quot;>Submit</button>
<button type=&quot;button&quot; class=&quot;btn btn-default&quot;
(click)=&quot;addHero()&quot;>New Hero</button>
</form>
</div>
<hero-submitted [hero]=&quot;hero&quot; [(submitted)]=&quot;submitted&quot;></hero-submitted>
</div>
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->"><input type="hidden" name="files[app/template/hero-form-template1.component.html]" value="<div class=&quot;container&quot;>
<div [hidden]=&quot;submitted&quot;>
<h1>Hero Form 1 (Template)</h1>
<form #heroForm=&quot;ngForm&quot; *ngIf=&quot;active&quot; (ngSubmit)=&quot;onSubmit()&quot;>
<div class=&quot;form-group&quot;>
<label for=&quot;name&quot;>Name</label>
<input type=&quot;text&quot; id=&quot;name&quot; class=&quot;form-control&quot;
required minlength=&quot;4&quot; maxlength=&quot;24&quot;
name=&quot;name&quot; [(ngModel)]=&quot;hero.name&quot;
#name=&quot;ngModel&quot; >
<div *ngIf=&quot;name.errors &amp;&amp; (name.dirty || name.touched)&quot;
class=&quot;alert alert-danger&quot;>
<div [hidden]=&quot;!name.errors.required&quot;>
Name is required
</div>
<div [hidden]=&quot;!name.errors.minlength&quot;>
Name must be at least 4 characters long.
</div>
<div [hidden]=&quot;!name.errors.maxlength&quot;>
Name cannot be more than 24 characters long.
</div>
</div>
</div>
<div class=&quot;form-group&quot;>
<label for=&quot;alterEgo&quot;>Alter Ego</label>
<input type=&quot;text&quot; id=&quot;alterEgo&quot; class=&quot;form-control&quot;
name=&quot;alterEgo&quot;
[(ngModel)]=&quot;hero.alterEgo&quot; >
</div>
<div class=&quot;form-group&quot;>
<label for=&quot;power&quot;>Hero Power</label>
<select id=&quot;power&quot; class=&quot;form-control&quot;
name=&quot;power&quot;
[(ngModel)]=&quot;hero.power&quot; required
#power=&quot;ngModel&quot; >
<option *ngFor=&quot;let p of powers&quot; [value]=&quot;p&quot;>{{p}}</option>
</select>
<div *ngIf=&quot;power.errors &amp;&amp; power.touched&quot; class=&quot;alert alert-danger&quot;>
<div [hidden]=&quot;!power.errors.required&quot;>Power is required</div>
</div>
</div>
<button type=&quot;submit&quot; class=&quot;btn btn-default&quot;
[disabled]=&quot;!heroForm.form.valid&quot;>Submit</button>
<button type=&quot;button&quot; class=&quot;btn btn-default&quot;
(click)=&quot;addHero()&quot;>New Hero</button>
</form>
</div>
<hero-submitted [hero]=&quot;hero&quot; [(submitted)]=&quot;submitted&quot;></hero-submitted>
</div>
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->"><input type="hidden" name="files[app/template/hero-form-template2.component.html]" value="<div class=&quot;container&quot;>
<div [hidden]=&quot;submitted&quot;>
<h1>Hero Form 2 (Template &amp; Messages)</h1>
<form #heroForm=&quot;ngForm&quot; *ngIf=&quot;active&quot; (ngSubmit)=&quot;onSubmit()&quot;>
<div class=&quot;form-group&quot;>
<label for=&quot;name&quot;>Name</label>
<input type=&quot;text&quot; id=&quot;name&quot; class=&quot;form-control&quot;
required minlength=&quot;4&quot; maxlength=&quot;24&quot; forbiddenName=&quot;bob&quot;
name=&quot;name&quot; [(ngModel)]=&quot;hero.name&quot; >
<div *ngIf=&quot;formErrors.name&quot; class=&quot;alert alert-danger&quot;>
{{ formErrors.name }}
</div>
</div>
<div class=&quot;form-group&quot;>
<label for=&quot;alterEgo&quot;>Alter Ego</label>
<input type=&quot;text&quot; id=&quot;alterEgo&quot; class=&quot;form-control&quot;
name=&quot;alterEgo&quot;
[(ngModel)]=&quot;hero.alterEgo&quot; >
</div>
<div class=&quot;form-group&quot;>
<label for=&quot;power&quot;>Hero Power</label>
<select id=&quot;power&quot; class=&quot;form-control&quot;
name=&quot;power&quot;
[(ngModel)]=&quot;hero.power&quot; required >
<option *ngFor=&quot;let p of powers&quot; [value]=&quot;p&quot;>{{p}}</option>
</select>
<div *ngIf=&quot;formErrors.power&quot; class=&quot;alert alert-danger&quot;>
{{ formErrors.power }}
</div>
</div>
<button type=&quot;submit&quot; class=&quot;btn btn-default&quot;
[disabled]=&quot;!heroForm.form.valid&quot;>Submit</button>
<button type=&quot;button&quot; class=&quot;btn btn-default&quot;
(click)=&quot;addHero()&quot;>New Hero</button>
</form>
</div>
<hero-submitted [hero]=&quot;hero&quot; [(submitted)]=&quot;submitted&quot;></hero-submitted>
</div>
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->"><input type="hidden" name="files[index.html]" value="<html>
<head>
<title>Hero Form with Validation</title>
<script>document.write('<base href=&quot;' + document.location + '&quot; />');</script>
<meta charset=&quot;UTF-8&quot;>
<meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;>
<link rel=&quot;stylesheet&quot; href=&quot;styles.css&quot;>
<link rel=&quot;stylesheet&quot; href=&quot;https://unpkg.com/bootstrap@3.3.7/dist/css/bootstrap.min.css&quot;>
<link rel=&quot;stylesheet&quot; href=&quot;styles.css&quot;>
<link rel=&quot;stylesheet&quot; href=&quot;forms.css&quot;>
<!-- Polyfills -->
<script src=&quot;https://unpkg.com/core-js/client/shim.min.js&quot;></script>
<script src=&quot;https://unpkg.com/zone.js@0.7.4?main=browser&quot;></script>
<script src=&quot;https://unpkg.com/systemjs@0.19.39/dist/system.src.js&quot;></script>
<script src=&quot;https://cdn.rawgit.com/angular/angular.io/b3c65a9/public/docs/_examples/_boilerplate/systemjs.config.web.js&quot;></script>
<script>
System.import('main.js').catch(function(err){ console.error(err); });
</script>
</head>
<body>
<my-app>Loading...</my-app>
</body>
</html>
<!--
Copyright 2016 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
-->"><input type="hidden" name="tags[0]" value="angular"><input type="hidden" name="tags[1]" value="example"><input type="hidden" name="private" value="true"><input type="hidden" name="description" value="Angular Example - Validation"></form><script>document.getElementById("mainForm").submit();</script></body></html>