<!DOCTYPE html>
<html>
<head>
<base href="." />
<script type="text/javascript" charset="utf-8">
window.AngularVersionForThisPlunker = 'latest'
</script>
<title>angular playground</title>
<link rel="stylesheet" href="style.css" />
<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>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
/* Styles go here */
### Angular Starter Plunker - Typescript
var angularVersion = '@4.4.6';
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@5.0.0',
'typescript': 'npm:typescript@2.2.1/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.module';
platformBrowserDynamic().bootstrapModule(AppModule)
//our root app component
import {Component} from '@angular/core'
@Component({
selector: 'my-app',
template: `
<h1>File upload required validation demo</h1>
<reactive-form></reactive-form>
<hr/>
<template-driven-form></template-driven-form>
`,
})
export class App {
}
import {Directive} from "@angular/core";
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from "@angular/forms";
@Directive({
selector: "input[type=file]",
host : {
"(change)" : "onChange($event.target.files)",
"(blur)": "onTouched()"
},
providers: [
{ provide: NG_VALUE_ACCESSOR, useExisting: FileValueAccessor, multi: true }
]
})
export class FileValueAccessor implements ControlValueAccessor {
value: any;
onChange = (_) => {};
onTouched = () => {};
writeValue(value) {}
registerOnChange(fn: any) { this.onChange = fn; }
registerOnTouched(fn: any) { this.onTouched = fn; }
}
import {Directive} from "@angular/core";
import {NG_VALIDATORS, Validator, FormControl} from "@angular/forms";
@Directive({
selector: "[requireFile]",
providers: [
{ provide: NG_VALIDATORS, useExisting: FileValidator, multi: true },
]
})
export class FileValidator implements Validator {
static validate(c: FormControl): {[key: string]: any} {
return c.value == null || c.value.length == 0 ? { "required" : true} : null;
}
validate(c: FormControl): {[key: string]: any} {
return FileValidator.validate(c);
}
}
import {NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import {FormsModule, ReactiveFormsModule} from '@angular/forms'
import {App} from './app'
import {ReactiveFormComponent} from './reactive-form.component'
import {TemplateDrivenFormComponent} from './template-driven-form.component'
import {FileValueAccessor} from './file-control-value-accessor'
import {FileValidator} from './file-input.validator'
@NgModule({
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule
],
declarations: [
App,
ReactiveFormComponent,
TemplateDrivenFormComponent,
FileValueAccessor,
FileValidator
],
bootstrap: [ App ]
})
export class AppModule {}
import {Component} from '@angular/core'
import {FormGroup, FormControl} from '@angular/forms'
import {FileValidator} from './file-input.validator'
@Component({
selector: 'reactive-form',
template: `
<h3>Reactive forms demo</h3>
<form [formGroup]="frm">
<input type="file" formControlName="file" />
<p *ngIf="frm.controls.file.errors?.required" style="color: red">This field is required!</p>
<div>
<button type="submit" [disabled]="!frm.valid">Submit</button>
</div>
</form>
`,
})
export class ReactiveFormComponent {
frm = new FormGroup({});
constructor() {
this.buildForm();
}
private buildForm() {
this.frm = new FormGroup({
file: new FormControl("", [FileValidator.validate])
});
}
}
import {Component} from '@angular/core'
import {FormGroup, FormControl} from '@angular/forms'
import {FileValidator} from './file-input.validator'
@Component({
selector: 'template-driven-form',
template: `
<h3>Template driven forms demo</h3>
<form #f="ngForm">
<input type="file" [ngModel]="fileContent" name="file" #file="ngModel" requireFile/>
<p *ngIf="!file.valid" style="color: red">This field is required!</p>
<div>
<button type="submit" [disabled]="!f.valid">Submit</button>
</div>
</form>
`,
})
export class TemplateDrivenFormComponent {
fileContent: any;
constructor() {
}
}