<!DOCTYPE html>
<html>
<head>
<base href="." />
<title>angular2 playground</title>
<link rel="stylesheet" href="style.css" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<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>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
/* Styles go here */
### Angular Starter Plunker - Typescript
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/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
'rxjs': 'npm:rxjs',
'typescript': 'npm:typescript@2.0.2/lib/typescript.js'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
}
}
});
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';
platformBrowserDynamic().bootstrapModule(AppModule)
//our root app component
import {NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
// By default, the app generated by ng init will include the FormsModule, here we’re requiring the ReactiveFormsModule as well
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
// Include the three components we created
import { SimpleFormComponent } from './app.simpleform';
import { ComplexFormComponent } from './app.complexform';
import { FormValidationComponent } from './app.formvalidation';
@NgModule({
declarations: [
AppComponent,
// Declare the three components as part of the root NgModule
SimpleFormComponent,
ComplexFormComponent,
FormValidationComponent,
],
imports: [
BrowserModule,
FormsModule,
// Including the ReactiveFormsModule in our application
ReactiveFormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
import { Component } from '@angular/core';
@Component({
selector: 'simple-form',
template : `
<div class="jumbotron">
<h2>Template Driven Form</h2>
<!-- Here we are declaring a local variable called “form” and setting it to an instance of ngForm. This is very important. Now our local form variable becomes of type FormGroup allowing us access to the FormGroup API’s on this local variable. We use this in the ngSubmit event where we send the value of the form via form.value -->
<form #form="ngForm" (ngSubmit)="submitForm(form.value)">
<div class="form-group">
<label>First Name:</label>
<!-- Since we are working with template driven forms, we can use the ngModel directive to capture the values of our forms. One thing to note if you are coming from Angular 1.x. Using ngModel as shown below creates a one-way data binding, so once we hit submit the data is only sent to the controller. If we wanted to use two-way data binding, we would have to wrap the ngModel in [()] and assign an attribute to it. Also the name of the field corresponds to the name attribute so our first input will be firstName. -->
<input type="text" class="form-control" placeholder="John" name="firstName" ngModel required>
</div>
<div class="form-group">
<label>Last Name</label>
<input type="text" class="form-control" placeholder="Doe" name="lastName" ngModel required>
</div>
<div class="form-group">
<label>Gender</label>
</div>
<!-- Radio and checkboxes work much the same way -->
<div class="radio">
<label>
<input type="radio" name="gender" value="Male" ngModel>
Male
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="gender" value="Female" ngModel>
Female
</label>
</div>
<div class="form-group">
<label>Activities</label>
</div>
<label class="checkbox-inline">
<input type="checkbox" value="hiking" name="hiking" ngModel> Hiking
</label>
<label class="checkbox-inline">
<input type="checkbox" value="swimming" name="swimming" ngModel> Swimming
</label>
<label class="checkbox-inline">
<input type="checkbox" value="running" name="running" ngModel> Running
</label>
<div class="form-group">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
</div>
`
})
export class SimpleFormComponent {
// Here we are implementing the submitForm function. All we are doing for right now is spitting out the details of the form to our console.
submitForm(form: any): void{
console.log('Form Data: ');
console.log(form);
}
}
import { Component } from '@angular/core';
// We will need to import a couple of specific API’s for dealing with reactive forms
import { FormBuilder, FormGroup } from '@angular/forms';
@Component({
selector: 'complex-form',
templateUrl : 'src/app.complexform.html'
})
export class ComplexFormComponent {
// The FormGroup object as you may remember from the simple form example exposes various API’s for dealing with forms. Here we are creating a new object and setting its type to FormGroup
complexForm : FormGroup;
// We are passing an instance of the FormBuilder to our constructor
constructor(fb: FormBuilder){
// Here we are using the FormBuilder to build out our form.
this.complexForm = fb.group({
// We can set default values by passing in the corresponding value or leave blank if we wish to not set the value. For our example, we’ll default the gender to female.
'firstName' : '',
'lastName': '',
'gender' : 'Female',
'hiking' : false,
'running' : false,
'swimming' : false
})
}
// Again we’ll implement our form submit function that will just console.log the results of our form
submitForm(value: any):void{
console.log('Reactive Form Data: ')
console.log(value);
}
}
import { Component } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
@Component({
selector: 'form-validation',
template : `
<div class="jumbotron">
<h2>Form with Validations</h2>
<form [formGroup]="complexForm" (ngSubmit)="submitForm(complexForm.value)">
<div class="form-group" [ngClass]="{'has-error':!complexForm.controls['firstName'].valid && complexForm.controls['firstName'].touched}">
<label>First Name:</label>
<input class="form-control" type="text" placeholder="John" [formControl]="complexForm.controls['firstName']">
<!-- The hasError method will tell us if a particular error exists -->
<div *ngIf="complexForm.controls['firstName'].hasError('required') && complexForm.controls['firstName'].touched" class="alert alert-danger">You must include a first name.</div>
</div>
<div class="form-group" [ngClass]="{'has-error':!complexForm.controls['lastName'].valid && complexForm.controls['lastName'].touched}">
<label>Last Name</label>
<input class="form-control" type="text" placeholder="Doe" [formControl]="complexForm.controls['lastName']">
<!-- The hasError method can work with the built in validators but custom validators as well -->
<div *ngIf="complexForm.controls['lastName'].hasError('required') && complexForm.controls['lastName'].touched" class="alert alert-danger">You must include a last name.</div>
<div *ngIf="complexForm.controls['lastName'].hasError('minlength') && complexForm.controls['lastName'].touched" class="alert alert-danger">Your last name must be at least 5 characters long.</div>
<div *ngIf="complexForm.controls['lastName'].hasError('maxlength') && complexForm.controls['lastName'].touched" class="alert alert-danger">Your last name cannot exceed 10 characters.</div>
</div>
<div class="form-group">
<label>Gender</label>
<div class="alert alert-danger" *ngIf="!complexForm.controls['gender'].valid && complexForm.controls['gender'].touched">You must select a gender.</div>
</div>
<div class="radio">
<label>
<input type="radio" name="gender" value="Male" [formControl]="complexForm.controls['gender']">
Male
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="gender" value="Female" [formControl]="complexForm.controls['gender']">
Female
</label>
</div>
<div class="form-group">
<label>Activities</label>
</div>
<label class="checkbox-inline">
<input type="checkbox" value="hiking" name="hiking" [formControl]="complexForm.controls['hiking']"> Hiking
</label>
<label class="checkbox-inline">
<input type="checkbox" value="swimming" name="swimming" [formControl]="complexForm.controls['swimming']"> Swimming
</label>
<label class="checkbox-inline">
<input type="checkbox" value="running" name="running" [formControl]="complexForm.controls['running']"> Running
</label>
<div class="form-group">
<button type="submit" class="btn btn-primary" [disabled]="!complexForm.valid">Submit</button>
</div>
</form>
</div>
`
})
export class FormValidationComponent {
complexForm : FormGroup;
constructor(fb: FormBuilder){
this.complexForm = fb.group({
// To add a validator, we must first convert the string value into an array. The first item in the array is the default value if any, then the next item in the array is the validator. Here we are adding a required validator meaning that the firstName attribute must have a value in it.
'firstName' : [null, Validators.required],
// We can use more than one validator per field. If we want to use more than one validator we have to wrap our array of validators with a Validators.compose function. Here we are using a required, minimum length and maximum length validator.
'lastName': [null, Validators.compose([Validators.required, Validators.minLength(5), Validators.maxLength(10)])],
'gender' : [null, Validators.required],
'hiking' : false,
'running' :false,
'swimming' :false
})
}
submitForm(value: any){
console.log(value);
}
}
import { Component } from '@angular/core'
@Component({
selector: 'my-app',
templateUrl : 'src/app.component.html',
})
export class AppComponent {
name:string;
constructor() {
this.name = 'Angular2'
}
}
<div class="container">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<simple-form></simple-form>
</div>
</div>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<complex-form></complex-form>
</div>
</div>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<form-validation></form-validation>
</div>
</div>
</div>
<div class="jumbotron">
<h2>Data Driven (Reactive) Form</h2>
<!-- Right of the bat, we no longer declare a local variable but use the formGroup directive and set it the complexForm object we defined in the constructor. Throughout the form, we will reference the complexForm root object as can be seen in the submitForm function.-->
<form [formGroup]="complexForm" (ngSubmit)="submitForm(complexForm.value)">
<div class="form-group">
<label>First Name:</label>
<!-- Rather than set an ngModel, we use the formControl directive to sync our input to the complexForm object. Notice that we are also setting the attribute we wish the corresponding input to sync with. We no longer need the name attribute, but can optionally add it. -->
<input class="form-control" type="text" placeholder="John" [formControl]="complexForm.controls['firstName']">
</div>
<div class="form-group">
<label>Last Name</label>
<input class="form-control" type="text" placeholder="Doe" [formControl]="complexForm.controls['lastName']">
</div>
<div class="form-group">
<label>Gender</label>
</div>
<div class="radio">
<label>
<input type="radio" name="gender" value="Male" [formControl]="complexForm.controls['gender']">
Male
</label>
</div>
<div class="radio">
<label>
<!-- This works the same way for radio and checkboxes as can be seen below -->
<input type="radio" name="gender" value="Female" [formControl]="complexForm.controls['gender']">
Female
</label>
</div>
<div class="form-group">
<label>Activities</label>
</div>
<label class="checkbox-inline">
<input type="checkbox" value="hiking" name="hiking" [formControl]="complexForm.controls['hiking']"> Hiking
</label>
<label class="checkbox-inline">
<input type="checkbox" value="swimming" name="swimming" [formControl]="complexForm.controls['swimming']"> Swimming
</label>
<label class="checkbox-inline">
<input type="checkbox" value="running" name="running" [formControl]="complexForm.controls['running']"> Running
</label>
<div class="form-group">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
</div>