What is the process of transforming two forms into components and then integrating those components into a view in Angular 5?

Currently, I have two forms running smoothly on the same component as shown in InfoAndQualificationComponent.ts

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from "@angular/forms";
@Component({
  selector: 'app-info-and-qualification',
  template: `<form class="form-horizontal" [formGroup]="form" (ngSubmit)="form.value">
    <div class="form-group">
    <input type="text" class="form-control" placeholder="firstname" formControlName="firstname">
  </div>
    <div class="form-group">
    <input type="text" class="form-control" placeholder="lastname" formControlName="lastname">
  </div>

  <div class="form-group"style="margin-top:50px">
    <input type="text" class="form-control" placeholder="Qualification" formControlName="qualification">
  </div>
    <div class="form-group">
    <input type="text" class="form-control" placeholder="Qualification type" formControlName="type">
  </div>
  <div class="form-group"><button class="btn-primary">Submit</button></div>
</
})
export class InfoAndQualificationComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

  form = new FormGroup({
    firstname: new FormControl(),
    lastname: new FormControl(),
    qualification: new FormControl(),
    qtype: new FormControl(),
  });

  onSubmit(e)
  {
    console.log(e);
  }
}

However, due to the clutter of code and the necessity for modularization (to make the code smaller for easier updates and debugging), I intend to split these forms into two different sub-components. First, for UserInfoComponent.ts:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from "@angular/forms";

@Component({
  selector: 'app-userinfo',
  template: `<form class="form-horizontal" [formGroup]="form1" (ngSubmit)="form1.value">
    <div class="form-group">
    <input type="text" class="form-control" placeholder="firstname" formControlName="firstname">
  </div>
    <div class="form-group">
    <input type="text" class="form-control" placeholder="lastname" formControlName="lastname">
  </div>

  <div class="form-group"><button class="btn-primary">Submit</button></div>
</form>`,

})
export class UserInfoComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

  form1 = new FormGroup({
    firstname: new FormControl(),
    lastname: new FormControl(),
  });

  onSubmit(e)
  {
    console.log(e);
  }
}

And for UserQualificationComponent.ts:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl } from "@angular/forms";

@Component({
  selector: 'app-qualification',
  template: `<form action="" class="form-horizontal" [formGroup]="form2"  (ngSubmit)="form2.value">
    <div class="form-group">
    <input type="text" class="form-control" placeholder="Qualification" formControlName="qualification">
  </div>
    <div class="form-group">
    <input type="text" class="form-control" placeholder="Qualification type" formControlName="qtype">
  </div>
  <div class="form-group"><button class="btn-primary">Submit</button></div>
</form>`,
})
export class UserQualificationComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

  form2 = new FormGroup({
    qualification: new FormControl(),
    qtype: new FormControl(),
  });

  onSubmit(e)
  {
    console.log(e);
  }
}

To simplify, both can be imported into one component like infoqualification.ts as follows:

<app-userinfo></app-userinfo>
<div style="margin-top:50px">
  <app-qualification></app-qualification>
</div>

Each component will have its own implementation in their respective components and will return values back to the main component. Please bear in mind that I am relatively new to Angular.

Answer №1

Utilize ControlContainer for Angular Forms

To learn more, visit the documentation here

import { Component } from '@angular/core';
import { ControlContainer, NgForm } from '@angular/forms';

@Component({
  selector: 'address',
  template: `
    <fieldset ngModelGroup="address">
      <div>
        <label>Zip:</label>
        <input type="text" name="zip" ngModel>
      </div>
      <div>
        <label>Street:</label>
        <input type="text" name="street" ngModel>
      </div>
      <div>
        <label>City:</label>
        <input type="text" name="city" ngModel>
      </div>
    </fieldset>
  `,
  viewProviders: [ { provide: ControlContainer, useExisting: NgForm } ]
})
export class AddressComponent  {}

For a detailed guide on nested template-driven forms in Angular, click here

Answer №2

Instead of creating individual FormGroup for every Component, consider creating a single Form Group in the parent component and passing it as an @Input() to the child components. This way, we can add form controls to the Form Group in the child components.

Additionally, you can create validation methods within each child component that can be called from the parent component.

The code for the Submit button and validation should be implemented in the parent component.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to reveal only the version information from the package.json file in an Angular 17 project?

Is there a secure way to extract and display only the version from a package.json file on the UI of a web application without exposing the rest of its contents? I am currently using the following structure in my package.json: { "name": "exa ...

Angular 6 triggers NavigationCancel event when encountering valid guards

I'm encountering difficulties with the Angular router while trying to navigate to a specific state. Despite my attempts to utilize a custom guard with canLoad() and canActivate() functions that return true, I have not been successful. The Angular do ...

The Angular downgradeComponent feature is experiencing difficulties in its creation process

I recently set up a hybrid application using AngularJS and Angular 5 with downgradeModule. I successfully converted a small component from AngularJS to Angular, but unfortunately, it is not being created. I've added console.logs in different parts of ...

Angular textbox with dynamic concatenated name functionality

Hello, I'm currently working with some code that looks like this: <div *ngFor="let phone of phoneList; let phIndx = index;"> <div class="peoplePhoneTxtDiv"> <input [disabled]="phone.disabled" class="peoplePhoneTxtBox" type="text" ...

Exploring the Validation of Forms in Angular for Practical Implementations

I'm curious to know whether creating a simple form validation process can really be as complicated as it seems, or if I may be overlooking something. It's fairly straightforward to demonstrate the power of form validation in a tutorial setting. ...

Angular route permissions and safety

Exploring the world of Angular has introduced me to its intricate routing mechanics and the use of routing guards for authorization on different routes. However, I can't help but feel like this guard mechanic may not be enough to fully secure my web s ...

Tips for utilizing interpolation for conditions instead of using *ngIf

For my application, I am using two different languages and have written them within two <option> tags. Is it possible to combine both conditions into a single <option> tag using interpolation? <option *ngIf="this.language=='en&apos ...

What is the best way to integrate ngx-translate's pipe for global translation?

I'm currently utilizing the ngx-translate package in order to internationalize my Angular application. When translating text using the translate pipe like so: {{ 'title' | translate }} An issue arises when attempting to use this pipe in ot ...

Change the value of the material slide toggle according to the user's response to the JavaScript 'confirm' dialogue

I am currently working on implementing an Angular Material Slide Toggle feature. I want to display a confirmation message if the user tries to switch the toggle from true to false, ensuring they really intend to do this. If the user chooses to cancel, I&ap ...

Steps to obtain the download URL from AngularFireStorage after uploading the file using the getDownloadUrl() method

After successfully uploading images into my firebase storage, I want to retrieve the downloadURL and add it to my firestore database. When console logging "url", I am able to see the desired link. However, I am facing difficulties in using it. When attemp ...

Unable to utilize vue-cookies library in TypeScript environment

I have integrated vue-cookies into my app in the main.ts file: import VueCookies from 'vue-cookies'; ... const app = createApp(App) .use(IonicVue) .use(router) .use(VueCookies,{ expires: '30d', }); Despite adding the cookie v ...

When using tsdx with React, null values can prevent proper usage of hooks

Recently, I attempted to develop a React TypeScript component using tsdx for compilation and encountered a roadblock while debugging. The package appears to be successfully published and installed without any errors. However, when trying to use it, I consi ...

Using NPM in combination with React and TypeScript to incorporate AMD modules

I am currently in the process of setting up a development environment for an application that is written in TypeScript using React. I already have existing TypeScript code that compiles to ES5 and AMD modules. My goal is to avoid any JavaScript transpilat ...

What is the best way to retrieve a value from async/await functions?

async function fetchNetworkStatus() { const network = await Network.getConnection(); setConnection(network.isConnected); console.log(connectionStatus); if (network.isConnected) { return true; } else { ...

Is it possible to customize the visible columns in a mat table based on the size of the screen?

Using mat-table, I have specified the columns to display in an array: In TypeScript: displayedColumns: string[] = ['date', 'customer', 'project', 'performanceRecord', 'duration', 'status', &apos ...

The Angular router is directed to an empty URL path instead of the specified URL

I have encountered a strange issue while developing my angular app which involves the router functionality. All routes were working perfectly fine until I discovered that after a successful login, instead of navigating to the '/admin' path as int ...

What is the best way to pass createdDt and updatedDat values in an Angular form without displaying them on the template?

I am working on a message creation form in Angular where I need to include createdDt and updatedDt as hidden values. These values should not be visible in the template. I want to automatically set the current date and time for both createdDt and updatedD ...

Using the useRef validation can lead to errors when trying to reference the current value against an input

Currently, the code is functioning well but an error alert from Typescript needs to be addressed. A warning pops up regarding the use of ref.current.value. ERROR 1. TS18048: 'ref.current' is possibly 'undefined'. To tackle this issue, ...

Oops! Before proceeding, make sure to call TestBed.initTestEnvironment() first

Currently, I am experimenting with testing a service in Angular. Below is the code snippet I am working on: describe('AddressService', () => { let service: AddressService; let injector: TestBed; let httpTestingController: HttpTesting ...

What is the best approach when one property of a typescript class relies on the values of two others?

Currently, I have a TypeScript class within an Angular application that consists of three properties. The first two properties can be changed independently using [(ngModel)]. However, I am looking for a way to set the third property as the sum of the first ...