Building a personalized Angular component to encapsulate an input field for use in reactive forms

I'm struggling to create a personalized component that includes an input form control. I'm unsure how to properly link the formControl directive and formControlName to the input element within my code. Here is what I have so far:

<div class="input-group">
    <input class="form-control form-control-sm"
        #code />
    <div class="input-group-append">
        <button type="button" class="btn btn-sm btn-success"
            (click)="search()">
            <i class="fa fa-search"></i>
        </button>
    </div>
</div>

This is the corresponding .ts file

import { Input, Component, forwardRef, OnInit, ViewChild } from '@angular/core';
import { DefaultValueAccessor, ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';

@Component({
    selector: 'search-input',
    templateUrl: './search-input.component.html',
    styleUrls: ['./search-input.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => SearchInputComponent),
            multi: true
        }
    ]
})
export class SearchInputComponent implements OnInit, ControlValueAccessor {
    writeValue(obj: any) {
    }

    registerOnChange(fn: any) {
    //this.valueAccesor.registerOnChange(fn);
    }

   registerOnTouched(fn: any) {
    //this.valueAccesor.registerOnTouched(fn);
   }

    setDisabledState(isDisabled: boolean) {
    //this.valueAccesor.setDisabledState(isDisabled);
    }
}

I would like to use it like this:

<search-input formControlName="code">

Or

<search-input formControl="code">

Any assistance or guidance on this matter would be greatly appreciated as I am relatively new to Angular development.

Answer №1

If you want a child component to interact with the same parent form, you need to pass the Parent Form instance as an input to the child component. The parent form will utilize the form builder to create the child form control, and the child component will define the template for the control.

Below is an example of a parent form (Sandbox) with a child component (AppTestInputForm):

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

@Component({
  selector: 'app-sandbox',
  templateUrl: './sandbox.component.html',
  styleUrls: ['./sandbox.component.css']
})
export class SandboxComponent implements OnInit {
  form: FormGroup;

  constructor(private formBuilder: FormBuilder) { 
    this.form = formBuilder.group({
      searchValue: new FormControl('')
    });
  }
  ngOnInit() {

  }

  submit() {
    if(this.form.valid) {
      console.log(this.form.get('searchValue').value, 'submitting search value');
    }
  }

}
<form [formGroup]="form" (ngSubmit)="submit()">
    <app-test-input-form [parentForm]="form"></app-test-input-form>
    <button type="submit" class="btn btn-primary">Submit</button>
 </form>

Here is the child component that includes the search input:

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

@Component({
  selector: 'app-test-input-form',
  templateUrl: './test-input-form.component.html',
  styleUrls: ['./test-input-form.component.css']
})
export class TestInputFormComponent implements OnInit {
  @Input() parentForm: FormGroup;

  constructor(private formBuilder: FormBuilder) { 

  }

  ngOnInit() {

  }

  search() {
    console.log('searching with value', this.parentForm.get('searchValue').value);
  }
}
<div class="input-group" [formGroup]="parentForm">
  <input class="form-control form-control-sm" formControlName="searchValue" />
  <div class="input-group-append">
    <button type="button" class="btn btn-sm btn-success" (click)="search()">
            <i class="fa fa-search"></i>
        </button>
  </div>
</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

Utilize Array in Form Input with Index and Spread Operator

Looking to create a form that can handle array data with dynamic fields in TypeScript. Encountering the following error: Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ nam ...

Why the CoreModule in Angular is a must-have for practical development

Though I have gained ample experience in developing Angular-UIs, there is one concept that continues to elude me - the true value of incorporating a CoreModule. To clarify, I understand the purpose of a SharedModule; it houses reusable components (such as ...

Encountered an issue while saving a blob in NativeScript: "Unable to convert object to [B at index

I have a Nativescript Angular application that is downloading a PDF from a Rails server in Blob Uint8Array format. When I attempt to save it, I encounter the following error: JS: /data/user/0/com.asset.management/files/result.pdf JS: ERROR Error: Uncaught ...

Steps to resolve the error "Cross-Origin Request Blocked: The Same Origin Policy prohibits reading the remote resource" in a project using Angular and .NET

Whenever I make an HTTP GET request to our API endpoints, I encounter errors indicating that the CORS header 'Access-Control-Allow-Origin' is missing. Our system consists of a SQL Server database connected to a .NET API with an Angular 7 front e ...

If I deselect an item, the "check all" option does not become deselected

I recently designed a page that displays all the weekdays and dates from Monday to Sunday. I added a feature where users can check all the weekdays with a single click, and uncheck them with another click. However, I encountered an issue where unchecking a ...

What steps should I take to create an object that can be converted into a JSON schema like the one shown here?

I'm facing a rather simple issue, but I believe there's something crucial that I'm overlooking. My objective is to iterate through and add elements to an object in order to generate a JSON structure similar to the following: { "user1": ...

What is the reason for not hashing the password in this system?

My password hashing code using Argon2 is shown below: import { ForbiddenException, Injectable } from '@nestjs/common'; import { PrismaService } from 'src/prisma/prisma.service'; import { AuthDto } from './dto'; import * as arg ...

What is preventing the dependency injection of AuthHttp (angular2-jwt) into a component?

UPDATE: Success! Problem Solved After much trial and error, I finally discovered the solution to my issue. It turned out that the problem lied in a simple configuration mistake. To rectify this, I made changes to both my package.json (dependencies section ...

Encountered an issue with the core-js postinstall script, causing a failure

I encountered the following errors while attempting to install node modules in an existing Angular project. The installation is being carried out on a Windows machine (Win32 X64). > [email protected] postinstall node_modules\babel-runti ...

Deactivating attribute inheritance / configuring component settings with script setup and Typescript

Is there a way to disable attribute inheritance for a component's options when using script setup syntax with Typescript in Vue 3? Here is the JavaScript code example: app.component('date-picker', { inheritAttrs: false, // [..] }) How ...

Issue with React TypeScript: Only the first state update takes effect, despite multiple updates being made

Check out this sandbox I created here. When you leave any of the form inputs blank, I should be seeing 3 errors but instead, I only get one. Can anyone explain why this is happening? import React, { ChangeEvent, useState } from 'react'; import { ...

What is the best way to send multiple values from the view to a method without using two-way binding?

https://i.sstatic.net/X4ivP.png When I change the dropdown value for the route type in my code, I need to pass both the gender value and the route type ID to my data retrieval method. Currently in my HTML file, I have only written a change event. I attem ...

Dimensions of Doughnut Chart in Chart.js

In my Angular project, I currently have two versions. The old production version uses an outdated version of ng2-charts, while I am working on upgrading it. Interestingly, I noticed a strange difference when using the doughnut chart from ng2-charts. When ...

Internet Explorer is throwing unexpected routing errors in Angular 2

I have a spring-boot/angular 2 application that is working perfectly fine on Chrome, Safari, Opera, and Edge. However, when accessed through Internet Explorer, the app directly routes to the PageNotFound component. I have tried adding shims for IE in the i ...

Tips for creating a window closing event handler in Angular 2

Can someone guide me on how to create a window closing event handler in Angular 2, specifically for closing and not refreshing the page? I am unable to use window.onBeforeunLoad(); method. ...

Maintain the specific type based on the provided data, rather than the default value, when a related generic is defined

When it comes to unit tests, I prefer a more flexible approach with dynamic generic types that eliminate the need for type casting. I want T to be open-ended, but if I specify a type, I expect to receive an exact match. For R, I need it to precisely matc ...

Tips for utilizing the patchValue method within a dynamic FormArray in Angular

When working with the first case (check out the DEMO link), patchValue() function can easily manipulate the select drop-down menu in a reactive FormGroup(), where only FormControl() is used. However, in the second case, I need to achieve the same functiona ...

Jasmine : Techniques for monitoring a method callback using method.then()

Within my Angular 4.0.0 application, I have a method called in my component. This method is invoked within a service: this.myService.myMethod(param).then(any => { console.log("success case"); }) .catch(error => { console.log("error"); }); ...

Deactivate the button permanently upon a single click

In the project I'm working on, there is a verification page for e-mail addresses. When new users register, they are sent an e-mail with a link to verify their e-mail. If the link is not clicked within a certain time frame, a button appears on the page ...

How can I store the data retrieved from an API and then forward it to a URL using Angular?

Is there a way to save and pass the data received from an API to a URL in Angular? SERVICE.ts readonly apiUrl = 'http://localhost:49940/'; constructor(private http: HttpClient) { } getUserName(): Observable<any> { return this.http.ge ...