connect the validation of forms to different components

I am currently working on components to facilitate the user addition process.

Below is an example of my form component:

createForm(): void {
    this.courseAddForm = this.formBuilder.group({
        name: ['', [
            Validators.required,
            Validators.maxLength(this.val.maxLen.title)
        ]],
        roleId: ['', Validators.compose([Validators.required])]
    });
}

name : represents the username,

roleId : is a field for selecting a role from a dropdown menu.

I have created a component called <kt-searchable-dropdown> specifically for the roleId selection.

The HTML structure is outlined below:

       <form id="courseAddForm" [formGroup]="courseAddForm" (ngSubmit)="onSubmit()" autocomplete="off">
                <div class="form-group kt-form__group row">
                    <!-- title -->
                    <div class="col-lg-6 kt-margin-bottom-20-mobile">
                        <mat-form-field class="mat-form-field-fluid" appearance="outline">
                            <mat-label>{{'GENERAL.TITLE' | translate}} *</mat-label>
                            <input matInput formControlName="title" [placeholder]="'GENERAL.TITLE' | translate">
                            <!--required error-->
                            <mat-error *ngIf="courseAddForm.get('title').errors?.required">
                                {{ 'VALIDATION.REQUIRED.TITLE' | translate }}</mat-error>
                            <!--length error-->
                            <mat-error *ngIf="courseAddForm.get('title').errors?.maxlength">
                                {{'VALIDATION.MAX_LENGTH' | translate}} {{val.maxLen.title}}
                            </mat-error>
                        </mat-form-field>
                    </div>

                    <div class="col-lg-6 kt-margin-bottom-20-mobile">
                        <kt-searchable-dropdown [formGroup]="courseAddForm" [formcontrolName]="'courseId'" (selectedId)="selectedCourse($event)"
                            [formTitle]="'COURSE.COURSE_GROUP'" [url]="url"></kt-searchable-dropdown>
                    </div>

                </div>
            </form>

I also have a custom component for handling the roleId dropdown selection:

In the TypeScript file:

export class SearchableDropdownComponent implements OnInit {

@Input() url: string;
@Input() formTitle: string;
@Input() ItemId: number;
@Input() formcontrolName: string;
@Input() formGroup: FormGroup;
@Output() selectedId = new EventEmitter<number>();

loading = false;
values: KeyValue[];
title: string;
fC: FormControl;

constructor(
    private searchService: SearchableDropDownService,
    private cdRef: ChangeDetectorRef) {

}

ngOnInit(): void {
    this.getValues(null);
}

getValues(event): void {

    this.cdRef.detectChanges();
    this.loading = true;

    let model = {} as SendDateModel;
    model.page = 1;
    model.pageSize = 60;
    model.title = event;

    this.searchService.getAll(this.url, model).subscribe(data => {
        this.values = data['result']['records'];
        this.cdRef.detectChanges();
        this.loading = false;
    });

}
}

In the HTML file:

<form [formGroup]="formGroup">
<mat-form-field appearance="outline">
    <mat-label>{{formTitle| translate}} *</mat-label>
    <mat-select formControlName="courseId" >
        <div class="col-lg-12 mt-4 kt-margin-bottom-20-mobile">
            <mat-form-field class="mat-form-field-fluid" appearance="outline">
                <mat-label>{{'GENERAL.TITLE' | translate}} *</mat-label>
                <input (keyup)="getValues($event.target.value)" matInput
                    [placeholder]="'GENERAL.TITLE' | translate">
            </mat-form-field>
        </div>
        <mat-progress-bar *ngIf="loading" class="mb-2" mode="indeterminate"></mat-progress-bar>
        <mat-option  (click)="emitdata(item.key)" *ngFor="let item of values"
            [(ngModel)]="ItemId" [value]="item.key">
            {{item.value}}
        </mat-option>
        <mat-error *ngIf="formGroup.get('courseId').errors?.required">
            {{ 'COURSE.VALIDATIONS.REQUIRED.CLASS_LEVEL' | translate }}</mat-error>
    </mat-select>
</mat-form-field>

However, I am encountering issues with the code implementation.

I am looking to implement validation binding in the form within these components. For instance, when the roleId field is required and the user does not select an item, an error should be displayed indicating that the roleId is mandatory. I would like to integrate this functionality into the SearchableDropdownComponent. How can I achieve this?

Answer №1

To implement this functionality, utilize angular observables. Develop a service to manage the error state in your primary component.

ErrorService.ts

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs/BehaviorSubject';

@Injectable()
export class ErrorService {

  private errorObj = new Subject<any>({});
  data = this.errorObj.asObservable();

  constructor() { }

  updatedErrorObj(error){
    this.errorObj.next(error);
  }

  getErrorObj(){
    return this.errorObj.asObservable();
  }
}

In the first component, instantiate this service and update the error object when an error occurs.

FirstComponent.ts

// Initialize the service in the constructor
constructor(private errorService: ErrorService) { }
onSubmit() {
    if(this.courseAddForm.invalid) {
        // Update error object
        cont errorObject = { key: 'value' }; //Define custom error object here
        this.errorService.updatedErrorObj(errorObject);

    }
}

Capture this error in the SearchableDropdownComponent

// Initialize the service in the constructor
constructor(private errorService: ErrorService) {
    errorService.getErrorObj.subscribe(data => {
      // Handle actions upon data changes
      // Receive the error object here.
    })
}

For more details, refer to this blog post.

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

Modify the parameters of the apps.facebook.com URL using the Facebook API

Is there a way to modify the parameters in the URL for apps.facebook.com using JavaScript? For instance, if a user chooses a photo, can we change the URL to apps.facebook.com/myapp/?photo_id=23234? This would allow the user to easily share the link with a ...

The useEffect hook is triggering multiple unnecessary calls

Imagine a tree-like structure that needs to be expanded to display all checked children. Check out this piece of code below: const { data } = useGetData(); // a custom react-query hook fetching data from an endpoint Now, there's a function that fin ...

Currently, I am compiling a list of tasks that need to be completed, but I am encountering a dilemma that is proving difficult to resolve

Recently delved into the world of Javascript and encountered a roadblock that I can't seem to overcome. Here's the snippet of code causing me trouble: add = document.getElementById("add"); add.addEventListener("click", () => { console.log("Ple ...

Activate the Keypress event to update the input value in React upon pressing the Enter

I am facing an issue where I need to reset the value of an input using a method triggered by onPressEnter. Here is the input code: <Input type="text" placeholder="new account" onPressEnter={(event) => this.onCreateAccount(event)}> < ...

What is the best way to transfer an object property to an event handler function for executing DOM manipulation tasks?

I am working on a React-rendered HTML page that displays a list of objects representing websites. I have successfully stored these objects in memory and can show them in a long list on the page without any issues. Recently, I added a button for each objec ...

Angular2 Eclipse: Eclipse Oxygen's HTML editor detects TypeScript errors in real-time

After installing the Eclipse Oxygen plugin for Angular2, I created a project using the Angular CLI and opened it in Eclipse. However, when trying to convert the project to an Angular project, I couldn't find the option under configuration. Instead, th ...

Is there a way to initiate the server only after webpack has finished bundling all of the bundles

"scripts": { "start": "node server.js", "build": "webpack" }, Is there a way to execute both npm run build and npm start with a single command? "scripts": { "start": " ...

Adapt the dimensions of the iframe to perfectly match the content within

Looking for a way to dynamically adjust the size of an iframe to perfectly fit its content, even after the initial load. It seems like I'll need some kind of event handling to automatically adjust the dimensions based on changes in the content within ...

Is there a way to locate an element within innerHTML using getElementById?

Is it possible to achieve the following code snippet? <div id="parent"> <iframe id="myFrame" title="HEY!" srcdoc="<div id='inner'>Hello World!</div>"></iframe> </div> v ...

Combining Layouts and Providers: A Guide to Using Both on a Single Page

I am facing an issue with my provider that is responsible for refreshing a token by making a request to the server. Additionally, I have a basic layout featuring a sidebar that I want to use only on a specific route. However, I am unsure about where to add ...

Ubuntu 16 is having difficulty identifying ng commands at the moment

It appears that the 'ng' program is not currently installed on this system. To install it, you can use the following command: sudo apt install ng-common I encountered no errors during the installation process. How should I go about resolving thi ...

jQuery's AJAX feature fails to identify the newly modified div classes

For my new website, I am developing a simple checklist feature. To handle the check and uncheck requests from users, I'm using jQuery's $.ajax() function. Whenever a user clicks on the check or uncheck buttons, jQuery retrieves the validation tok ...

Creating a radial progress chart using Plotly JavaScript

I recently started working with the Plotly library and now I need to display a circular progress graph in Vuejs 2, like the one shown below. While Plotly is a comprehensive tool, I have not come across an example that matches this specific design using Ja ...

Change the URL structure from ex.com/forum?id=1 to ex.com/#/forum?id=1 in AngularJS

Hey there! I'm in the process of creating a Forum using AngularJS and need some guidance. First things first! I've successfully established a connection to my database with: <?php session_start(); $db = new mysqli("localhost","root",""," ...

Tips for incorporating additional filter criteria into a jquery script

I am currently utilizing a jQuery script to filter data based on date periods. However, I now need to include an additional filtering criteria for the "POSITION" column. Since I lack expertise in jQuery, I would rather accomplish this using plain vanilla J ...

React - The content of my JSON.String vanishes upon being placed inside a div element

My NFTDetails component includes a description from a JSON, which contains \n\n in it. Strangely, there are no new lines when I render the JSON value in a div, but when I log it to the console in Firefox, new lines appear. How can I make use of ...

Require assistance in understanding JSON data in the form of a variable

Apologies for any language barriers, but I have encountered a problem that I need help with. I am trying to create a highchart from an AJAX call. The following code works perfectly: chartOptions = { chart: { renderTo: 'grafica1', type: 'ar ...

Is there a method to avoid redeclaring variables in JavaScript with jQuery?

In the structure of my code, I have the following setup. <!-- first.tpl --> <script> $(document).ready(function() { objIns.loadNames = '{$names|json_encode}'; } ) </script> {include file="second.tpl"} <! ...

Angular reactive forms with Material date picker enables the setting of date in the format of YYYY-MM-DDT00:00:00

I am trying to use Material DatePicker with Moment for date formatting while using reactive forms. Here is the code where I set the value for NextDeliverDate in the .ts file: loadData() { this.getSubscriptionData().subscribe((x) => { this.sub ...

Can general principles be applied to determine which script is the most efficient and will load the quickest?

Is there a way to determine which script is optimal and will load faster when there are multiple ways to write scripts that achieve the same outcome? ...