Form validation is an essential feature of the Angular2 template-driven sub form component

I'm currently working on a template-driven form that includes a group of inputs generated through an ngFor.

My goal is to separate this repeating 'sub-group' into its own child component. However, I'm encountering difficulties in ensuring that the parent ngForm recognizes and applies the validation rules from the child component.

Here's a simplified example illustrating the issue:

Parent Template:

<form #parentForm="ngForm">
    <input name="firstName" ngModel required>
    <input name="lastName" ngModel required>

    <child-component *ngFor="let child of children;"></child-component>
</form>

Child Template:

<div>
    <input name="foo" required ngModel>
    <input name="bar" required ngModel>
</div>

I've attempted to make the parent form recognize the required attributes set in the child inputs by placing the child within its own form and passing the instance of #parentForm to the child, followed by calling:

this.parentForm.addFormGroup(this.childForm.form)

Unfortunately, this approach hasn't yielded the desired results.

Alternatively, I've tried having the parent form fetch the ContentChildren of the sub forms and integrating each one into the main form. Yet, the validation still doesn't function as expected.

While aware that implementing ControlValueAccessor in the subcomponent could potentially solve the issue, I prefer not to go down that route as it would entail developing custom validators for existing validations such as required.

If you have any insights on how I can successfully incorporate a sub-form into the parent while leveraging the child's validation settings, your assistance would be greatly appreciated.

Answer №1

One way to potentially solve this issue is by enabling communication between child components and parent forms through additional controls:

child.component.ts

@Component({
  selector: 'child-component',
  template: `
   <div>
    <input name="foo" required ngModel>
    <input name="bar" required ngModel>
  </div>
  `
})
export class ChildComponent {
  @ViewChildren(NgModel) controls: QueryList<NgModel>;

  constructor(private parentForm: NgForm) { }

  ngAfterViewInit() {
    this.controls.forEach((control: NgModel) => {
      this.parentForm.addControl(control);
    });
  }
}

Check out the example on Plunker

Answer №2

To solve your issue, you can utilize property binding and @Input in the following manner:

<form #parentForm="ngForm">
    <input name="firstName" ngModel required>
    <input name="lastName" ngModel required>

    <child-component #parentForm.childForm="ngForm" [children]="kids"></child-component>
</form>

Implement the following steps to make it work:

  1. Create an input variable like this:

    @Input() kids:any[]=[];
    
  2. Update the template as shown below:

    <div *ngFor="let kid of kids;">
       <input name="bar" required [(ngModel)]="kid.bar"/>
    </div>
    

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

Utilizing React and TypeScript: Passing Arguments to MouseEventHandler Type Event Handlers

Can you help me understand how to properly define the event handler handleStatus as type MouseEventHandler, in order to pass an additional argument of type Todo to the function? interface TodoProps { todos: Array<Todos> handleStatus: Mous ...

Strategies for optimizing PPI and DPI in responsive design

Imagine having two monitors: one 15.5 inches with a resolution of 1920 x 1080 and the other 24 inches with the same resolution. The first monitor has a pixel density of around 72 PPI, while the second has around 90 PPI. If I apply a media query in CSS for ...

Manipulate Browser Navigation Behavior using JavaScript or AngularJS

How to Manage Browser Back Button Behavior Using AngularJS or JavaScript This is not a question, but rather a demonstration of how you can disable and manipulate the behavior of the browser's back button when using AngularJS or plain JavaScript. ...

The function `Object.entries().map()` in TypeScript does not retain the original data types. What changes can I make to my interface to ensure it works correctly, or is there a workaround

Working with this interface: export interface NPMPackage { name: string; description: string; 'dist-tags': { [tag: string]: string; }; versions: { [version: string]: { name: string; version: string; dependencie ...

Uncovering the Mystery Behind the Repetitive Execution of useEffect in Next.js

I am working on a Time Tracking feature for my Next.js application. In the ./app/components/TimeTracking.tsx file, I have implemented the following component: 'use client'; import React, { useEffect, useState } from 'react'; import { u ...

The Radio button and Checkbox values are causing an issue where the Radio button is continuously summing upon clicking without a limit. Why is this happening? Check out

I'm currently stuck in a function and believe it would be helpful for you to guide me along the correct path. My goal is to sum the values of checked boxes with the values of checked radio buttons. However, the radio values are continuously accumulat ...

Guide to Implementing Kendo-Grid in Angular 4 CLI

Having trouble using the Kendo-Grid in Angular4? You may encounter this error message: Uncaught Error: Template parse errors: 'Kunden-grid' is not a known element: 1. If 'Kunden-grid' is an Angular component, then verify that it is par ...

What could be causing my ASP.Net MVC script bundles to load on every page view?

I'm a bit puzzled. The _layout.cshtml page I have below contains several bundles of .css and .js files. Upon the initial site load, each file in the bundles is processed, which makes sense. However, every time a new view is loaded, each line of code f ...

Preventing the "save" button from being enabled until a change has been made to at least one input field

I have a page with approximately 20 input fields, along with save and register buttons. Is there a way to activate the "save" button only when a change has been made in at least one of the fields? ...

Adapting Angular routes in real-time using observable state modifications

I am currently working on an Angular project that involves Angular routing. The code snippet below is extracted from my app-routing.module.ts file: // app-routing.module.ts: import { NgModule } from '@angular/core'; import { ActivatedRout ...

Enhance the function for handling AJAX responses

Utilizing this code allows for the handling of responses from an RSS feed. The code efficiently organizes and appends content, separating any embedded videos. While seeking feedback primarily on performance/efficiency, I am also open to other suggestions. ...

Utilizing a library across various files in Node.js

I am looking to integrate Winston for logging in my nodejs express project. Within my main file ( server.js ) I currently have the following code snippet: const winston = require('winston'); winston.level = process.env.LOG_LEVEL winston.log(&ap ...

Unlocking the Power of $http and Stream Fusion

I'm interested in accessing the public stream of App.net. However, when I attempt to retrieve it using a simple $http.get(), I only receive one response. $http .get('https://alpha-api.app.net/stream/0/posts/stream/global') .success(func ...

Issue encountered when making API requests in JavaScript that is not present when using Postman

Currently, I am developing a web application using express and one of the functionalities is exposed through an API with an endpoint on 'api/tone'. This API acts as a wrapper for one of Watson's services but I choose not to call them directl ...

What is the best way to bind data to a textarea component and keep it updated?

I started using VueJS just a week ago for a new project. During this time, I have successfully created two components: * Account.vue (Parent) <!--This snippet is just a small part of the code--> <e-textarea title="Additional Information" ...

Client-side resizing an image before sending it to PHP for uploading

Greetings! Currently, I am utilizing a JavaScript library from this source to resize images on the client-side. The image resizing process works successfully with the following code: document.getElementById('foto_select').onchange = function( ...

An element in CSS that has a position of fixed and a width of 100% surpasses the dimensions of its

My element has the CSS properties position:fixed and width:100%, causing it to be larger than its parent elements. Despite the complexity of my code, I have attempted to simplify it for better understanding. Below, you can see that the green box exceeds ...

Cypress encountered an error: Module '../../webpack.config.js' could not be located

Every time I attempt to run cypress, an error pops up once the window launches stating "Error: Cannot find module '../../webpack.config.js'" Within my plugins>index.js file, I have the following in module.exports webpackOptions: require(&apos ...

What is the best way to have setState function properly within setInterval? (currently functioning somewhat)

function timerFunction(){ const [time, setTime] = useState(10); var timeRemaining = 10; const myInterval = setInterval(() => { if (timeRemaining > 0) { timeRemaining = timeRemaining - 1; setTime(timeRemaining); } els ...

Tips for resolving the final item issue in Owl Carousel when using right-to-left (RTL)

Encountering a bug with the rtl setting in owl-carousel. When the rtl is applied to the slider and I reach the last item, the entire slider disappears! Here's the code snippet: var viewportWidth = $("body").innerWidth(); if (viewportWidth & ...