Frazer
Frazer

Reputation: 5

Create a Contact form in Angular 2 / 4 that POSTS JSON to a specified API

I'm trying to create an Angular 2 / 4 project that has a 'Contact Us' form that creates data via JSON.stringify to then POST to my API that I have setup in AWS API Gateway. This uses Lambda and SES to email the details to me.

I am struggling learning Angular 2 / 4 and an working example of such type of form would be a terrific learning tool to amend and learn from.

I have followed many Angular 2 example videos and read tutorials, but, I'm unable to find a simple form that POSTs JSON to an API to follow/amend.

Any help would be greatly appreciated folks! :)

Upvotes: 0

Views: 1671

Answers (1)

Tiep Phan
Tiep Phan

Reputation: 12596

Form in Angular is powerful and easy to use. Let's build a simple form with Reactive Form.

1: We grab all NgModule we need to use Reactive Form and call AJAX with Http:

import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from './app.component';

@NgModule({
  imports: [ 
    BrowserModule, 
    HttpModule, // for http request
    ReactiveFormsModule // for form system
  ],
  declarations: [ AppComponent ],
  providers: [ ],
  bootstrap: [ AppComponent ]
})
export class AppModule {}

2: And our AppComponent look like this:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { FromGroup, FormBuilder, Validators } from '@angular/forms';

@Component({
  selector: 'app-form',
  template: `
    <h2>Contact Form</h2>
    <form [formGroup]="frmContact" (ngSubmit)="onSubmit()" novalidate>
      <div>
        <label>
          Name:
          <input type="text" formControlName="name">
        </label>
      </div>
      <div>
        <label>
          Comment:
          <textarea formControlName="content"></textarea>
        </label>
      </div>
      <button [disabled]="frmContact.invalid">Submit</button>
    </form>

    <div *ngIf="res">
      Response:
      <pre>{{ res | json }}</pre>
    </div>
  `,
})
export class AppComponent implements OnInit, OnDestroy {
  frmContact: FormGroup;
  private _sub;

  res: any;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.frmContact = this.fb.group({
      name: ['', Validators.required],
      content: ['', Validators.required]
    });
  }

  onSubmit() {
    let formValue = this.frmContact.value;
    // cool stuff to transform form value

    // call AJAX

  }

  ngOnDestroy() {
    // clean subscription when component destroy
    if (this._sub) {
      this._sub.unsubscribe();
    }
  }

}

We inject FormBuilder class to AppComponent to create our form when Component Init.

And we use Validators to use pre-built Validator function - required for example.

In component template, we use some directive formGroup, formControlName to bind our form to template.

3: Now, we need a service to communicate with server:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class PostService {
  private API_ENDPOINT = '//jsonplaceholder.typicode.com/posts'; //replace with your API ENDPOINT
  constructor(private _http: Http) {}

  saveContact(contact: any) {
    return this._http.post(this.API_ENDPOINT, contact)
      .map(res => res.json());
  }
}

Maybe in some case, you need include Header (Authorization token, for example), you need create header like this:

let headers = new Headers({ 'Content-Type': 'application/json' }); // create new Headers object with header Content-Type is application/json.
headers.append('Authorization', 'Bearer ' + your_token); //JWT token
let options = new RequestOptions({ headers: headers });

And send request with header:

saveContact(contact: any) {
  let headers = new Headers({ 'Content-Type': 'application/json' }); // create new Headers object with header Content-Type is application/json.
  headers.append('Authorization', 'Bearer ' + your_token); //JWT token
  let options = new RequestOptions({ headers: headers });
  return this._http.post(this.API_ENDPOINT, contact, options)
    .map(res => res.json());
}

4: Update AppComponent and AppModule to use service

AppModule

// other import
import { PostService } from './post.service';

@NgModule({
  imports: [ 
    //...
  ],
  declarations: [ AppComponent ],
  providers: [ PostService ], // declare our service into this array
  bootstrap: [ AppComponent ]
})
export class AppModule {}

AppComponent

// other import

import { PostService } from './post.service';

@Component({
  //...
})
export class AppComponent implements OnInit, OnDestroy {
  frmContact: FormGroup;
  private _sub;

  res: any;

  constructor(private fb: FormBuilder, private postService: PostService) {}

  ngOnInit() {
    //...
  }

  onSubmit() {
    let formValue = this.frmContact.value;
    // cool stuff to transform form value

    // call AJAX
    this._sub = this.postService.saveContact(formValue)
      .subscribe(data => {
        console.log(data)
        this.res = data;
      });
  }

  ngOnDestroy() {
    // clean subscription when component destroy
    if (this._sub) {
      this._sub.unsubscribe();
    }
  }

}

When user click to button submit, onSubmit method will execute, then it'll call service method this.postService.saveContact to send your data.

You can play with Live Demo here: https://plnkr.co/edit/GCYsGwreHi13FejcWDtE?p=preview

Document: https://angular.io/docs/ts/latest/guide/server-communication.html

Upvotes: 1

Related Questions