<!DOCTYPE html>
<html>
<head>
<title>Angular Material Plunker</title>
<!-- Load common libraries -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/typescript/2.1.6/typescript.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zone.js/0.7.2/zone.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.47/system.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.2.2/web-animations.min.js"></script>
<!-- Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System
.import('main.ts')
.catch(console.error.bind(console));
</script>
<!-- Load the Angular Material stylesheet -->
<link href="https://rawgit.com/angular/material2-builds/master/prebuilt-themes/indigo-pink.css" rel="stylesheet">
<style>body { font-family: Roboto, Arial, sans-serif; margin: 0 }</style>
</head>
<body class="mat-app-background">
<material-app>Loading the Angular Material App...</material-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
-->
import {Component} from '@angular/core';
import {Http} from '@angular/http'
import {bootstrap} from '@angular/platform-browser-dynamic';
import {MyMaterialComponent} from './material.component';
import 'rxjs/add/operator/map'
@Component({
selector: 'material-app',
templateUrl: 'app.component.html'
})
export class AppComponent {
private version: any;
constructor(http: Http) {
// Display the currently used Material 2 version.
this.version = http
.get('https://api.github.com/repos/angular/material2-builds/commits/HEAD')
.map(res => res.json())
}
}
/*
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
*/
<md-toolbar color="primary">
Angular Material 2 App
</md-toolbar>
<div style="padding: 7px">
<p>
----- SOME MATERIAL COMPONENTS -----<br/>
<button md-button>Basic Button</button>
<md-slide-toggle>Slide Toggle</md-slide-toggle>
</p>
<br/><br/>
----- DYNAMIC FORM EXAMPLE -----<br/>
<my-form-material></my-form-material>
</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
-->
/** Add Transpiler for Typescript */
System.config({
transpiler: 'typescript',
typescriptOptions: {
emitDecoratorMetadata: true
},
packages: {
'.': {
defaultExtension: 'ts'
},
'vendor': {
defaultExtension: 'js'
}
}
});
System.config({
map: {
'main': 'main.js',
// Angular specific mappings.
'@angular/core': 'https://unpkg.com/@angular/core/bundles/core.umd.js',
'@angular/common': 'https://unpkg.com/@angular/common/bundles/common.umd.js',
'@angular/compiler': 'https://unpkg.com/@angular/compiler/bundles/compiler.umd.js',
'@angular/animations': "https://unpkg.com/@angular/animations/bundles/animations.umd.js",
'@angular/animations/browser': 'https://unpkg.com/@angular/animations/bundles/animations-browser.umd.js',
'@angular/http': 'https://unpkg.com/@angular/http/bundles/http.umd.js',
'@angular/forms': 'https://unpkg.com/@angular/forms@4.3.1',
'@angular/router': 'https://unpkg.com/@angular/router/bundles/router.umd.js',
'@angular/platform-browser': 'https://unpkg.com/@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser/animations': 'https://unpkg.com/@angular/platform-browser/bundles/platform-browser-animations.umd.js',
'@angular/platform-browser-dynamic': 'https://unpkg.com/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/material': 'https://unpkg.com/@angular/material@2.0.0-beta.8',
'@angular/cdk': 'https://unpkg.com/@angular/cdk@2.0.0-beta.8',
"@ng2-dynamic-forms/core": "https://unpkg.com/@ng2-dynamic-forms/core@1.4.20",
"@ng2-dynamic-forms/ui-material": "https://unpkg.com/@ng2-dynamic-forms/ui-material@1.4.20",
// Third party libraries
'tslib': 'https://unpkg.com/tslib@1.7.1',
'rxjs': 'https://unpkg.com/rxjs',
},
packages: {
// Thirdparty barrels.
'rxjs': { main: 'index' },
}
});
/*
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
*/
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {BrowserModule} from '@angular/platform-browser';
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {HttpModule} from '@angular/http';
import {AppComponent} from './app.component';
import {MyMaterialComponent} from './material.component';
import {CdkTableModule} from '@angular/cdk'
import {
MdAutocompleteModule,
MdButtonModule,
MdButtonToggleModule,
MdCardModule,
MdCheckboxModule,
MdChipsModule,
MdCoreModule,
MdDatepickerModule,
MdDialogModule,
MdExpansionModule,
MdGridListModule,
MdIconModule,
MdInputModule,
MdListModule,
MdMenuModule,
MdNativeDateModule,
MdProgressBarModule,
MdProgressSpinnerModule,
MdRadioModule,
MdRippleModule,
MdSelectModule,
MdSidenavModule,
MdSliderModule,
MdSlideToggleModule,
MdSnackBarModule,
MdTabsModule,
MdToolbarModule,
MdTooltipModule,
OverlayModule
} from '@angular/material';
import { FormsModule, ReactiveFormsModule, NG_VALIDATORS, NG_ASYNC_VALIDATORS, AbstractControl, ValidationErrors, ValidatorFn, FormGroup } from '@angular/forms';
import { DynamicFormsCoreModule } from "@ng2-dynamic-forms/core";
import { DynamicFormsMaterialUIModule } from "@ng2-dynamic-forms/ui-material";
import { ChangeOptionsService } from "./changeoptions.service";
/**
* NgModule that includes all Material modules that are required to serve
* the Plunker.
*/
@NgModule({
exports: [
// CDk
CdkTableModule,
// Material
MdAutocompleteModule,
MdButtonModule,
MdButtonToggleModule,
MdCardModule,
MdCheckboxModule,
MdChipsModule,
MdDatepickerModule,
MdDialogModule,
MdExpansionModule,
MdGridListModule,
MdIconModule,
MdInputModule,
MdListModule,
MdMenuModule,
MdCoreModule,
MdProgressBarModule,
MdProgressSpinnerModule,
MdRadioModule,
MdRippleModule,
MdSelectModule,
MdSidenavModule,
MdSlideToggleModule,
MdSliderModule,
MdSnackBarModule,
MdTabsModule,
MdToolbarModule,
MdTooltipModule,
MdNativeDateModule,
// Material (future CDK)
OverlayModule,
]
})
export class PlunkerMaterialModule {}
@NgModule({
imports: [
BrowserModule,
CommonModule,
HttpModule,
PlunkerMaterialModule,
BrowserAnimationsModule,
FormsModule,
ReactiveFormsModule,
DynamicFormsCoreModule.forRoot(),
DynamicFormsMaterialUIModule
],
declarations: [AppComponent,MyMaterialComponent],
bootstrap: [AppComponent],
providers: [
ChangeOptionsService,
{provide: NG_VALIDATORS, useValue: areaValidator, multi: true},
{provide: NG_ASYNC_VALIDATORS, useValue: areaGroupValidator, multi: true}
]
})
export class PlunkerAppModule {}
platformBrowserDynamic().bootstrapModule(PlunkerAppModule);
// Validator for inputModels to chech value if is valid for LandHeight
export function areaValidator(control: AbstractControl): ValidationErrors | null {
let maxArea:number = 50000
let hasError = control.value ? !(Number(control.value) >= 0 && Number(control.value) <= maxArea): false;
return hasError ? {areaValidator: true} : null;
}
// Validator for inputModels to chech value if is valid for LandHeight
export function areaGroupValidator() {
return function(formGroup: FormGroup): Promise<ValidationErrors | null> {
let TotalArea = formGroup.controls.areaInput.value;
let SubArea = formGroup.controls.subAreaInput.value
if (SubArea > TotalArea) {
return new Promise((resolve, reject) => {
resolve({areaGroupValidator: true});
});
} else {
return new Promise((resolve, reject) => {
resolve(null);
});
}
}
}
/*
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
*/
<div class="content-margin" style="width: 50%;">
<form class="text-center" >
<dynamic-form-material-control *ngFor="let controlModel of formModel"
[group]="formGroup"
[model]="controlModel"
[hasErrorMessaging]="controlModel.hasErrorMessages"
[showCharacterHint]="controlModel.type === 'INPUT'"
(change)="onChange($event)"></dynamic-form-material-control>
</form>
<pre>{{formGroup.value | json}}</pre>
</div>
import { Component, OnInit, ViewEncapsulation } from "@angular/core";
import { FormGroup, FormControl, FormArray } from "@angular/forms";
import {
DynamicFormService,
DynamicCheckboxModel,
DynamicFormControlModel,
DynamicFormArrayModel
} from "@ng2-dynamic-forms/core";
import { MATERIAL_EXAMPLE_MODEL } from "./material.model";
import { ChangeOptionsService } from "./changeoptions.service";
@Component({
selector: "my-form-material",
templateUrl: "./material.component.html",
encapsulation: ViewEncapsulation.None
})
export class MyMaterialComponent implements OnInit {
formModel: DynamicFormControlModel[] = MATERIAL_EXAMPLE_MODEL;
formGroup: FormGroup;
checkboxControl: FormControl;
checkboxModel: DynamicCheckboxModel;
selectControl: DynamicSelectModel;
arrayControl: FormArray;
arrayModel: DynamicFormArrayModel;
constructor(private formService: DynamicFormService, private changeOptionsService: ChangeOptionsService) {
}
ngOnInit() {
this.formGroup = this.formService.createFormGroup(this.formModel);
this.checkboxControl = this.formGroup.controls["exampleCheckbox"] as FormControl;
this.checkboxModel = this.formService.findById("exampleCheckbox", this.formModel) as DynamicCheckboxModel;
this.arrayControl = this.formGroup.controls["materialFormArray"] as FormArray;
this.arrayModel = this.formService.findById("materialFormArray", this.formModel) as DynamicFormArrayModel;
this.selectControl = this.formService.findById("materialSelect", this.formModel) as DynamicSelectModel;
this.selectControl.options = this.changeOptionsService.newOptions();
}
add() {
this.formService.addFormArrayGroup(this.arrayControl, this.arrayModel);
}
remove(index: number) {
this.formService.removeFormArrayGroup(index, this.arrayControl, this.arrayModel);
}
onChange($event) {
console.log(`CHANGE event on: `, $event);
}
}
import {
DynamicCheckboxModel,
DynamicCheckboxGroupModel,
DynamicDatePickerModel,
DynamicInputModel,
DynamicRadioGroupModel,
DynamicSelectModel,
DynamicSliderModel,
DynamicSwitchModel,
DynamicTextAreaModel,
DynamicFormGroupModel
} from "@ng2-dynamic-forms/core";
import { areaValidator, areaGroupValidator } from "./main";
export const MATERIAL_EXAMPLE_MODEL = [
new DynamicSelectModel<string>(
{
id: "materialSelect",
//label: "Example Select",
multiple: false,
options: [
{
label: "Option 1",
value: "option-1",
},
{
label: "Option 2",
value: "option-2"
},
{
label: "Option 3",
value: "option-3"
},
{
label: "Option 4",
value: "option-4"
}
],
placeholder: "Select an option"
}
),
new DynamicInputModel(
{
id: "materialInput",
list: ["Abies", "Pinus", "Fagus", "Platanus"],
maxLength: 51,
placeholder: "Select Plant",
validators: {
required: null
},
errorMessages: {
required: "Field is required"
}
}
),
new DynamicFormGroupModel(
{
id: "areas",
label: "Forest Area",
group: [
new DynamicInputModel(
{
id: "areaInput",
inputType : "number",
min: 0,
step: .5,
placeholder: "Total Area (Ha)",
validators: {
required: null,
areaValidator: {
name: areaValidator.name,
args: null
}
},
errorMessages: {
required: "Field Area is required",
areaValidator: "Area [0 - 50.000m]"
}
}
),
new DynamicInputModel(
{
id: "subAreaInput",
inputType : "number",
min: 0,
step: .5,
placeholder: "sub Area input",
validators: {
required: null,
areaValidator: {
name: areaValidator.name,
args: null
}
},
errorMessages: {
required: "Field Area is required",
areaValidator: "Area [0 - 50.000m]"
}
}
)
],
asyncValidator : {
areaGroupValidator:areaGroupValidator
},
errorMessages: {
areaGroupValidator: "sub Area > Total Area ERROR !!!"
}
}),
new DynamicDatePickerModel(
{
id: "materialDatepicker",
placeholder: "Material Datepicker",
value: new Date()
}
),
new DynamicCheckboxGroupModel(
{
id: "materialCheckboxGroup",
group: [
new DynamicCheckboxModel(
{
id: "materialCheckbox1",
label: "Checkbox 1"
}
),
new DynamicCheckboxModel(
{
id: "materialCheckbox2",
label: "Checkbox 2"
}
)
]
}
),
new DynamicSwitchModel(
{
id: "materialSwitch",
offLabel: "Off",
onLabel: "On",
value: false
}
),
new DynamicRadioGroupModel<string>(
{
id: "materialRadioGroup",
//label: "Example Option",
options: [
{
label: "Option 1",
value: "option-1",
},
{
disabled: true,
label: "Option 2",
value: "option-2"
},
{
label: "Option 3",
value: "option-3"
},
{
label: "Option 4",
value: "option-4"
}
],
relation: [
{
action: "DISABLE",
when: [
{
id: "materialSwitch",
value: true
}
]
}
],
value: "option-3"
}
),
new DynamicSliderModel(
{
id: "materialSlider",
min: 0,
max: 10,
step: 1,
value: 3,
vertical: false
}
),
new DynamicTextAreaModel(
{
id: "materialTextArea",
//label: "Example Textarea",
rows: 1,
placeholder: "example Textarea",
validators: {
required: null
},
errorMessages: {
required: "Field is required"
}
}
),
new DynamicCheckboxModel(
{
id: "materialCheckbox",
label: "I do agree"
}
)
];
import { Injectable } from '@angular/core';
@Injectable()
export class ChangeOptionsService {
private N_Categories : Array<any>;
constructor() {
this.N_Categories = [
{
label: "New Option 1",
value: "a-1",
},
{
label: "New Option 2",
value: "a-2"
},
{
label: "New Option 3",
value: "a-3"
},
{
label: "New Option 4",
value: "a-4"
}
]
}
newOptions() {
return this.N_Categories;
}
}