Angular mat-auto-complete should be validated after the final user input

Implementing custom validation for auto-completion in a template-driven form.

The challenge: the validator function is being triggered with the previous user input value.

HTML

<mat-form-field *ngIf="configObj(controls)['type']=== 'employees'">
  <input matInput #employeesf [matTooltip]="configObj(controls)['tooltip']||controls" placeholder="{{controls}}"
    formControlName="{{controls}}"
    [required]="configObj(controls)['require']==='yes'|| configObj(controls)['require']==true "
    (ngModelChange)="_filterEmployees(employeesf.value)" [matAutocomplete]="employeeInput"
    placeholder="{{'translate.select_employee' | translate}}" required appHasSelectedOptionValidator
    [options]="filteredClients" [userInput]="[clientf.value]" />
  <mat-autocomplete panelWidth="auto" #employeeInput="matAutocomplete" (optionSelected)="employeeClick($event)">
    <mat-option *ngFor="let employee of filteredEmployees" [value]="employee">
      {{employee}}
    </mat-option>
  </mat-autocomplete>
  <mat-hint *ngIf="configObj(controls)['display_old_answer']">{{hints[controls]}}</mat-hint>
  <mat-hint *ngIf="!configObj(controls)['display_old_answer'] && configObj(controls)['hint']">
    {{configObj(controls)['hint']}}
  </mat-hint>
</mat-form-field>

TS (hasSelectedOptionValidator.ts)

import { Directive, Input } from '@angular/core';
import { NG_VALIDATORS, Validator } from '@angular/forms';

@Directive({
  selector: '[appHasSelectedOptionValidator]',
  providers: [
    { provide: NG_VALIDATORS, useExisting: HasSelectedOptionValidatorDirective, multi: true }
  ]
})
export class HasSelectedOptionValidatorDirective implements Validator {

  @Input("options") options: string[]
  @Input("userInput") userInput: any

  validate(c: FormControl) {
    console.log('options ', this.options)
    console.log('input ', this.userInput)
    let subby = [];
    this.options.forEach(element => subby.push(element[0]));

    console.log('sub: ', subby);

    if (subby.includes(this.userInput[0])) {
      console.log('in');
      return null;
    } else {

      console.log('not in')

      console.log('subby ', subby)
      console.log('input ', this.userInput[0])

      return { 'selected': false };
    }
  }
}

Is there a way to update the validation check based on the most recent user input, especially when the user selects an option from the auto-completion menu?

Answer №1

It turns out that there is a constant value that updates in real-time

TS

import { Validator, NG_VALIDATORS, FormControl } from '@angular/forms'
import {Directive, Input, OnChanges} from '@angular/core';

@Directive({
  selector: '[appHasSelectedOptionValidator]',
  providers: [
    { provide: NG_VALIDATORS, useExisting: HasSelectedOptionValidatorDirective, multi: true }
  ]
})
export class HasSelectedOptionValidatorDirective implements Validator, OnChanges {

  @Input() options :string[]
  @Input() userInput: any;

  validate(c: FormControl) {
    console.log('input is ', c.value)
    console.log('options ', this.options)

    let subby = [];
    this.options.forEach(element => subby.push(element[0]));

    console.log('sub: ', subby);

    if (subby.includes(c.value)) {
      console.log('in');
      return null;
    } else {

      console.log('not in')

    console.log('subby ', subby)
    console.log('input ', c.value)

      return {'selected': false};
    }
  }
}

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

Building Dynamic Grids with Kendo UI in Angular2: A Step-by-Step Guide

When using the Grid component, I already have a few columns predefined in the HTML. However, the result set may contain additional columns that are not known until after the data is retrieved. Is there a way to dynamically add these extra columns? After f ...

The 'validate' property within the 'MappingService' class cannot be assigned to the 'validate' property in the base class 'IMappingService' in typescript version 2.8.0

Currently, I am utilizing the AngularJS framework (version 1.5.8) in tandem with the latest TypeScript files (2.8.0). However, upon updating to the newest version of TypeScript, the code below is failing to compile. The IMappingService interface: export ...

Encountering a multitude of challenges when attempting to seamlessly integrate aframe into an angular2 project, especially when incorporating unit tests

I'm encountering issues with integrating aframe 0.7.0 effectively into my angular 4.3.6 (angular-cli 1.0.0) project. The error messages I am receiving include: Chrome 61.0.3163 (Windows 10 0.0.0) LOG: '%cA-Frame:warn %cPut the A-Frame <script ...

The challenge of customizing the theme in Angular 18

I recently started updating my code from Angular 16 to the latest version, which is Angular 18. Below is the snippet of code I've implemented, but it's causing compilation errors: @use '@angular/material' as mat; // Define custom pale ...

What is the process for specifying a dependency on an ng-metadata module?

I am currently working on a project that is utilizing ng-metadata for creating a few Angular 1.5 modules. One of the test modules/components in this project has the following structure: import { NgModule, Component, Inject, Input, Output, EventEmitter } f ...

What is the best way for Jasmine to utilize the FormGroup super constructor within the ngOnInit lifecycle hook?

I have created a custom form class that extends FormGroup and has the following constructor: public constructor(/* parameters */) { function myValidator(): ValidatorFn { //return validator function } super({ /* form controls */}, [myVal ...

Using a template literal with the keyof operator as an interface property

Imagine a scenario where we have a basic interface: interface Schedule { interval: "month" | "day"; price: number; } We can create a template-literal type with TypeScript version 4.4: type PrefixedScheduleKey = `schedule__${keyof S ...

Triggering ngSubmit function when button is clicked inside an Ionic alert

My ionic app is up and running, utilizing a template driven form in Angular to gather user input. I'm using ngSubmit to pass this data to my ts.file. My challenge lies in triggering the ngSubmit function through a 'No and save data' button w ...

Can class properties be automatically generated based on its generic type?

Is it possible in TypeScript to automatically create a class with properties based on its generic type? For example: class CustomClass<T> { // Code to extract properties from T should go here } interface Characteristics { quality: string; pri ...

Tips for applying personalized CSS to the ngbDatepicker component in Angular 4

Here is the HTML code I am working with: <div> <div style="color:white">Date Range:</div> <div class="input-daterange input-group"> <input class="form-control" value="2017-01-01" name="dp1" ...

Combining two objects by aligning their keys in JavaScript

I have two simple objects that look like this. var obj1 = { "data": { "Category": "OUTFLOWS", "Opening": 3213.11, "Mar16": 3213.12, "Apr16": 3148.13, "May16": 3148.14, "Jun16" ...

How to check all checkboxes in Angular using ngFor and ngIf?

Is there a way to select all checkboxes in an Angular form that uses ngFor and ngIf? I want to activate all checkboxes for the months when I click on "Select All". The list of months is stored in an array. Click here to see the HTML representation of the ...

The most efficient and hygienic method for retrieving a value based on an observable

Looking at the structure of my code, I see that there are numerous Observables and ReplaySubjects. When trying to extract a value from one of these observables in the HTML template, what would be the most effective approach? In certain situations, parame ...

Analyzing the 'inactive' attribute of mat-checkbox

I am facing difficulty in changing the disabled property of mat-checkbox - https://material.angular.io/components/checkbox/api <mat-checkbox (change)="itemChanged()" [(ngModel)]="item.selected" [disableAfterClick]=" ...

Angular2 component not loading properly despite correct resolution by Webstorm

Currently, I am exploring a seed from https://github.com/NathanWalker/angular2-seed-advanced The following are the src files available: app.component.ts import { ChangeDetectionStrategy } from 'angular2/core'; import { RouteConfig } from &apos ...

The modules 'MdCardModule' and 'MdTooltipModule' do not have any exported members

Encountering Errors After Running ng build Issue found in C:/761/search- bar/workload_management_app/Client/src/app/app.module.ts (8,9): Module '"C:/761/search- bar/workload_management_app/Client/node_modules/@angular/materia ...

Tips for effectively mocking a service class in a hybrid Angular project to facilitate unit testing

I'm currently working on a hybrid Angular project, but I've encountered some challenges with unit testing. Despite trying out this solution, it doesn't seem to be effective for my particular project. I keep receiving an error when running ...

How to display placeholder text on multiple lines in Angular Material's mat form field

Within a standard mat-form-field, I have a textarea enclosed. However, the placeholder text for this Textarea is quite lengthy, leading to truncation with an ellipsis on mobile devices due to limited space. My goal is to adjust the placeholder text based ...

What is the best way to access the property from the outcome of the jwt.verify() function that has been previously generated

Within my node.js project, I've incorporated typescript for development. I encountered an issue while trying to extract the userId from the output of jwt.verify(). How can I resolve this obstacle? (The error only occurs when using typescript.) Insi ...

Ways to troubleshoot the error message 't.rangeslider is not a function' in which rangeslider is a personalized function

I'm experiencing an issue with a function assigned to a variable that is throwing an error. Here is the code snippet: $(".sliderRange").each(function() { var t = $(this); t.rangeslider({ polyfill: !1, onSlide: function(e, a) { var n = ...