|
|
a |
|
|
\ No newline at end of file |
|
|
### Form validation example (http://blog.ng-book.com/the-ultimate-guide-to-forms-in-angular-2/)
|
|
|
```javascript
|
|
|
...
|
|
|
import { ValidationService } from '../../services';
|
|
|
import { ControlArray, ControlGroup } from '@angular/common';
|
|
|
import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms';
|
|
|
|
|
|
@Component...
|
|
|
export class ContactForm implements OnInit {
|
|
|
private contactForm: FormGroup;
|
|
|
|
|
|
public constructor (private formBuilder: FormBuilder) {}
|
|
|
|
|
|
public ngOnInit () {
|
|
|
this.buildForm();
|
|
|
}
|
|
|
|
|
|
private buildForm () {
|
|
|
let nameControl = ['', Validators.required]; // can also use other initial value instead of empty string
|
|
|
let emailControl = ['', ValidationService.emailValidator];
|
|
|
let subjectControl = ['', Validators.required];
|
|
|
let bodyControl = ['', Validators.required];
|
|
|
|
|
|
this.contactForm = this.formBuilder.group({
|
|
|
full_name: nameControl,
|
|
|
email: emailControl,
|
|
|
subject: subjectControl,
|
|
|
body: bodyControl,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
private submitForm (form: any): void {
|
|
|
if (form.valid) {
|
|
|
let payload = form.value;
|
|
|
this.Contact.create(payload).subscribe((res: any) => {
|
|
|
this.buildForm();
|
|
|
this.handleSuccess();
|
|
|
}, (err: any) => {
|
|
|
console.log(err);
|
|
|
});
|
|
|
}
|
|
|
else {console.log('FORM: INVALID');}
|
|
|
}
|
|
|
|
|
|
...
|
|
|
|
|
|
}
|
|
|
```
|
|
|
|
|
|
|
|
|
## Custom app-global error handling
|
|
|
```typescript
|
|
|
import { ErrorHandler } from '@angular/core';
|
|
|
|
|
|
class CustomErrorHandler implements ErrorHandler {
|
|
|
public handleError (error: any) {
|
|
|
// originalError is probably the message you want in a toast, etc
|
|
|
console.log(error.originalError);
|
|
|
// still send error to console, if desired
|
|
|
console.error(error._nativeError);
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
```
|
|
|
import { NgModule, ErrorHandler } from '@angular/core';
|
|
|
import { CustomErrorHandler } from './path/to/custom/handler';
|
|
|
...
|
|
|
@NgModule({
|
|
|
...
|
|
|
providers: [
|
|
|
{provide: ErrorHandler, useClass: CustomErrorHandler},
|
|
|
],
|
|
|
})
|
|
|
```
|
|
|
|
|
|
## ngFor filtering (ngChange on input which updates array)
|
|
|
|
|
|
## Add the following for errors to appear and disappear automatically
|
|
|
|
|
|
```scss
|
|
|
/* FORMS, INPUTS
|
|
|
----------------------------------------*/
|
|
|
input, textarea {
|
|
|
display: inline-block;
|
|
|
padding: 16px 28px;
|
|
|
border: none;
|
|
|
outline: none;
|
|
|
box-shadow: none;
|
|
|
border-radius: 60px;
|
|
|
color: $gray;
|
|
|
@include font-range(14, 18);
|
|
|
@include sans;
|
|
|
@include placeholder {
|
|
|
color: $grayLt;
|
|
|
@include sans;
|
|
|
@include font-range(14, 18);
|
|
|
}
|
|
|
}
|
|
|
input.ng-invalid.ng-dirty, textarea.ng-invalid.ng-dirty {
|
|
|
border-left: solid red 3px !important;
|
|
|
}
|
|
|
input.ng-valid.ng-dirty, textarea.ng-valid.ng-dirty {
|
|
|
border-left: solid #42A948 3px !important;
|
|
|
}
|
|
|
```
|
|
|
## Example of errors in form HTML
|
|
|
```html
|
|
|
<div class="careerDetail">
|
|
|
<div class="careerDetail__content">
|
|
|
<section class="careerOutline">
|
|
|
<h2 class="careerOutline__title">{{ (career | async)?.title }}</h2>
|
|
|
<div class="careerOutline__location">{{ (career | async)?.location }}</div>
|
|
|
<div [innerHtml]="(career | async)?.description"></div>
|
|
|
</section>
|
|
|
<section class="apply">
|
|
|
<form [formGroup]="applyForm" (submit)="onSubmit(applyForm)">
|
|
|
<div class="apply__header">
|
|
|
APPLY FOR THIS POSITION
|
|
|
</div>
|
|
|
<div class="apply__form">
|
|
|
<input required [formControl]="applyForm.controls['full_name']" class="apply__input" type="text" placeholder="Full Name *">
|
|
|
<input required [formControl]="applyForm.controls['city']" class="apply__input" type="text" placeholder="City*">
|
|
|
<input required [formControl]="applyForm.controls['email']" class="apply__input" type="email" placeholder="Email*">
|
|
|
<input required [formControl]="applyForm.controls['phone_number']" class="apply__input" type="text" placeholder="Phone*">
|
|
|
<div class="formError" *ngIf="applyForm.controls['phone_number'].touched && applyForm.controls['phone_number'].hasError('invalidInternationalPhoneNumber') &&
|
|
|
applyForm.controls['phone_number'].value.length > 0">
|
|
|
Number needs to be in International format. ex) +18881231234
|
|
|
</div>
|
|
|
<textarea required [formControl]="applyForm.controls['message']" class="apply__textarea" placeholder="Message (required)"
|
|
|
rows="10"></textarea>
|
|
|
<input required accept='.doc,.pdf,.txt' id="fileInput" class="apply__fileInput" type="file">
|
|
|
<div class="formError" *ngIf="fileError">
|
|
|
{{fileError}}
|
|
|
</div>
|
|
|
<button [disabled]="!applyForm.valid || fileError" type="submit" class="button"> Apply </button>
|
|
|
</div>
|
|
|
</form>
|
|
|
</section>
|
|
|
</div>
|
|
|
</div>
|
|
|
```
|
|
|
## Component for form errors
|
|
|
``` javascript
|
|
|
import { Component, OnInit } from '@angular/core';
|
|
|
import { Router, ActivatedRoute } from '@angular/router';
|
|
|
import { ValidationService, APIConfigService, HttpService, CareerModel } from '../../shared';
|
|
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|
|
@Component({
|
|
|
selector: 'app-career',
|
|
|
templateUrl: './career.component.html',
|
|
|
styleUrls: ['./career.component.scss']
|
|
|
})
|
|
|
export class CareerComponent implements OnInit {
|
|
|
private user: {} = undefined;
|
|
|
private career: Promise<{}>;
|
|
|
private careerId: number;
|
|
|
private applyForm: FormGroup;
|
|
|
private success: boolean = false;
|
|
|
private apiUrl: any = this.apiConfig.apiUrl;
|
|
|
private file: any;
|
|
|
private fileError: string = '';
|
|
|
public constructor(
|
|
|
private validation: ValidationService,
|
|
|
private apiConfig: APIConfigService,
|
|
|
private Career: CareerModel,
|
|
|
private route: ActivatedRoute,
|
|
|
private router: Router,
|
|
|
private formBuilder: FormBuilder,
|
|
|
private http: HttpService
|
|
|
) {
|
|
|
}
|
|
|
public ngOnInit() {
|
|
|
this.buildForm();
|
|
|
this.route.params.subscribe(params => {
|
|
|
this.career = this.Career.read(params['id'])
|
|
|
.then(career => {
|
|
|
this.careerId = career.id;
|
|
|
return career;
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
ngAfterViewInit() {
|
|
|
// Component views are initialized
|
|
|
this.file = document.getElementById('fileInput');
|
|
|
this.file.onchange = () => {
|
|
|
let ext = this.file.files[0].name.match(/\.([^\.]+)$/)[1];
|
|
|
if (ext !== ('pdf' || 'doc' || 'txt')) {
|
|
|
this.fileError = 'accepted formats .pdf, .doc, .txt';
|
|
|
}
|
|
|
else { this.fileError = '' }
|
|
|
}
|
|
|
}
|
|
|
private buildForm() {
|
|
|
let nameControl = ['', Validators.required];
|
|
|
let emailControl = ['', Validators.compose([Validators.required, this.validation.emailValidator])];
|
|
|
let cityControl = ['', Validators.required];
|
|
|
let phoneControl = ['', Validators.compose([Validators.required, this.validation.phoneInternationalValidator])];
|
|
|
let bodyControl = ['', Validators.required];
|
|
|
this.applyForm = this.formBuilder.group({
|
|
|
full_name: nameControl,
|
|
|
email: emailControl,
|
|
|
city: cityControl,
|
|
|
phone_number: phoneControl,
|
|
|
message: bodyControl,
|
|
|
});
|
|
|
}
|
|
|
private onSubmit(form: any): void {
|
|
|
if (form.valid) {
|
|
|
let payload = form.value;
|
|
|
let url = this.apiUrl + '/jobs/' + this.careerId + '/apply/';
|
|
|
let file: any = document.getElementById('fileInput');
|
|
|
file = file.files[0];
|
|
|
let ext = file.name.match(/\.([^\.]+)$/)[1];
|
|
|
if (ext === ('pdf' || 'doc' || 'txt')) {
|
|
|
// file = file.files[0];
|
|
|
let data = new FormData();
|
|
|
Object.keys(payload).map((key) => {
|
|
|
data.append(key, payload[key]);
|
|
|
});
|
|
|
data.append('resume', file, file.name);
|
|
|
this.http.clearToken('Content-Type');
|
|
|
this.http.post(url, data).subscribe((r: any) => {
|
|
|
this.buildForm();
|
|
|
this.success = true;
|
|
|
setTimeout(() => { this.success = false; }, 3000);
|
|
|
}, (err: any) => {
|
|
|
console.log(err);
|
|
|
});
|
|
|
}
|
|
|
else {
|
|
|
alert('File is not a .doc,.txt, or .pdf format');
|
|
|
}
|
|
|
}
|
|
|
else { console.log('FORM: INVALID'); }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
``` |
|
|
\ No newline at end of file |