Same form for creating and editing data Angular4

Viewed 61778

Here is a form with two way-binded input fields. The goal was to create the same form to edit and create data. That was accomplished, but I am pretty sure that there could be a better way to do this (like using AbstractControl features). I also miss one fix here - if clickEdit() being clicked need to update form values with that object which user wants to edit. Thanks for any help and especially explanations about AbstractControl and NgModel..

<div>
<form (ngSubmit)="clicked ? onEditSubmit($event) : onRegisterSubmit($event)" [formGroup] = "form">
  <div class="form-group">
    <label>Full Name</label>
    <input type="text" [(ngModel)]="fullname" formControlName="fullname" class="form-control" >

  </div>
  <div class="form-group">
    <label>Username</label>
    <input type="text" [(ngModel)]="username" formControlName="username" class="form-control" >
  </div>
  <div class="form-group">
    <label>Email</label>
    <input type="text" [(ngModel)]="email" formControlName="email" class="form-control" >
  </div>
  <div class="form-group">
    <label>Password</label>
    <input type="password" [(ngModel)]="password" formControlName="password" class="form-control">
  </div>
  <button type="submit" class="btn btn-primary" [disabled]="!form.valid"> Submit </button>
</form>
</div>

<br>
<br>

<table  border="2" class="table table-striped">
<tr>
  <th>Full Name</th>
  <th>Username</th>
  <th>Email</th>
  <th>Password</th>
  <th>Delete</th>
  <th>Edit</th>
</tr>
<div > </div>
<tr *ngFor="let user of userDetails; index as i">
  <td>{{user.fullname}}</td>
  <td>{{user.username}}</td>
  <td>{{user.email}}</td>
  <td>{{user.password}}</td>
  <td><button (click)="userDelete()">X</button></td>
  <td><button (click)="clickEdit(i)">Edit</button></td>
</tr>
</table>

And

import { Component } from '@angular/core';
import { initializeApp, database } from 'firebase';
import { FormControl, FormGroup, Validators } from '@angular/forms';


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {

  fullname : string;
  username : string;
  email : string;
  password : string;

  clicked = false;

  userDetails:Array<object>;

  form;

  ngOnInit() {
   this.userDetails=[];
    this.form = new FormGroup({
      fullname : new FormControl("", Validators.required),
      username : new FormControl("", Validators.required),
      email : new FormControl("", Validators.required),
      password : new FormControl("", Validators.required)
    });
  }

  onRegisterSubmit(e){
    let user = {
      fullname : this.fullname ,
      username : this.username,
      email : this.email ,
      password : this.password
    }
     this.userDetails.push(user);
     this.clearInputFields(e);
   }

   editIndex = null;

  clickEdit(i){
    this.clicked = !this.clicked;
    this.editIndex = i;
  }

  onEditSubmit(e) {
    let editUser = {
      fullname : this.fullname ,
      username : this.username,
      email : this.email ,
      password : this.password
    }
    this.userDetails[this.editIndex] = editUser;
    this.clearInputFields(e);  
    this.clicked = !this.clicked;  
  }

  clearInputFields(e){
   let all = e.target.querySelectorAll('input');
    Object.keys(all).forEach(key => {
        console.log(all[key].value = '');   
    });    
  }
}
2 Answers

Dummy Forms

Creating Form that are reusable.

Folder Structure

enter image description here

Usage

User Form Component

<form (ngSubmit)="submit(form)" [formGroup] = "form">
  <input type="text" formControlName="username" >
  <button type="submit"[disabled]="!form.valid"> Submit</button>
  <button type="button" (click)="cancel()"></button>
</form>
@Input() formData;
@Output() onSubmit = new EventEmitter();
@Output() onCancel = new EventEmitter();

ngOnInit(){
    this.form = this.fb.group({
      username : ['', Validators.required]
    });

    // Edit Mode will have formData.
    if(this.formData){
        this.form.patchValue(this.formData)
    }
}

submit(){
   if(this.form.valid){
       this.onSubmit.emit(this.form.value)
   }
}

cancel(){
  this.onCancel.emit();
}

Add User Component

<user-form                  
    (onSubmit)="addUser($event)"  
    (onCancel)="cancel()">
</user-form>
addUser(data){
   // Call Http Service to save data
}

cancel(){
   // navigate to different route or something else
}

Edit User Component

<user-form 
    [formData]="formData"                 
    (onSubmit)="updateUser($event)"  
    (onCancel)="cancel()">
</user-form>
ngOnInit(){
   this.formData = //fetch data from server 
}

updateUser(data){
   // Call Http Service to save data
}

cancel(){
   // navigate to different route or something else
}

Pros

  1. Single Component for single use
  2. Can reuse the dummy forms anywhere throughout the application.
  3. Easy to maintain and extend the form

Cons

  1. For each page you will have 3 components ( add, edit, form).
Related