[ACS-8998] Added validation to search input to disallow certain special characters (#4253)

* [ACS-8998] Added validation to search input to disallow certain special characters

* [ACS-8998] Search input now replaces text: with TEXT: on submit, instead of giving a validation error

* [ACS-8998] Reverted unneeded padding change

* [ACS-8998] Calling search term getter instead of searchFormControl.value directly
This commit is contained in:
swapnil-verma-gl 2024-12-18 12:37:33 +05:30 committed by GitHub
parent 07d0203f74
commit 111f3f99e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 28 deletions

View File

@ -5,7 +5,7 @@
mat-icon-button mat-icon-button
matPrefix matPrefix
class="app-search-button" class="app-search-button"
(click)="searchSubmit(searchTerm)" (click)="searchSubmit()"
[title]="'SEARCH.BUTTON.TOOLTIP' | translate" [title]="'SEARCH.BUTTON.TOOLTIP' | translate"
> >
<mat-icon [attr.aria-label]="'SEARCH.BUTTON.ARIA-LABEL' | translate">search</mat-icon> <mat-icon [attr.aria-label]="'SEARCH.BUTTON.ARIA-LABEL' | translate">search</mat-icon>
@ -17,15 +17,14 @@
[attr.aria-label]="'SEARCH.INPUT.ARIA-LABEL' | translate" [attr.aria-label]="'SEARCH.INPUT.ARIA-LABEL' | translate"
[type]="inputType" [type]="inputType"
id="app-control-input" id="app-control-input"
[(ngModel)]="searchTerm" [formControl]="searchFieldFormControl"
(ngModelChange)="inputChange($event)" (keyup.enter)="searchSubmit()"
(keyup.enter)="searchSubmit($event)"
[placeholder]="'SEARCH.INPUT.PLACEHOLDER' | translate" [placeholder]="'SEARCH.INPUT.PLACEHOLDER' | translate"
autocomplete="off" autocomplete="off"
/> />
<div matSuffix> <div matSuffix>
<button mat-icon-button (click)="clear()"> <button mat-icon-button (click)="clear()">
<mat-icon *ngIf="searchTerm.length" class="app-suffix-icon">clear</mat-icon> <mat-icon *ngIf="searchFieldFormControl.value.length" class="app-suffix-icon">clear</mat-icon>
</button> </button>
</div> </div>
</mat-form-field> </mat-form-field>

View File

@ -43,31 +43,29 @@ describe('SearchInputControlComponent', () => {
}); });
it('should emit submit event on searchSubmit', () => { it('should emit submit event on searchSubmit', () => {
const keyboardEvent = { target: { value: 'a' } }; component.searchTerm = 'mock-search-term';
let eventArgs = null; let submittedSearchTerm = '';
component.submit.subscribe((args) => (eventArgs = args)); component.submit.subscribe((searchTerm) => (submittedSearchTerm = searchTerm));
component.searchSubmit(keyboardEvent); component.searchSubmit();
expect(eventArgs).toBe(keyboardEvent); expect(submittedSearchTerm).toBe('mock-search-term');
}); });
it('should emit searchChange event on inputChange', () => { it('should emit searchChange event on inputChange', () => {
const searchTerm = 'b'; let emittedSearchTerm = '';
component.searchChange.subscribe((searchTerm) => (emittedSearchTerm = searchTerm));
component.searchTerm = 'mock-search-term';
let eventArgs = null; expect(emittedSearchTerm).toBe('mock-search-term');
component.searchChange.subscribe((args) => (eventArgs = args));
component.inputChange(searchTerm);
expect(eventArgs).toBe(searchTerm);
}); });
it('should emit searchChange event on clear', () => { it('should emit searchChange event on clear', () => {
let eventArgs = null; let emittedSearchTerm: string = null;
component.searchChange.subscribe((args) => (eventArgs = args)); component.searchChange.subscribe((searchTerm) => (emittedSearchTerm = searchTerm));
component.clear(); component.clear();
expect(eventArgs).toBe(''); expect(emittedSearchTerm).toBe('');
}); });
it('should clear searchTerm', () => { it('should clear searchTerm', () => {

View File

@ -22,25 +22,28 @@
* from Hyland Software. If not, see <http://www.gnu.org/licenses/>. * from Hyland Software. If not, see <http://www.gnu.org/licenses/>.
*/ */
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core'; import { Component, EventEmitter, Input, Output, ViewEncapsulation, ViewChild, ElementRef, OnInit, inject, DestroyRef } from '@angular/core';
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core'; import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { FormsModule } from '@angular/forms'; import { FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
@Component({ @Component({
standalone: true, standalone: true,
imports: [CommonModule, TranslateModule, MatButtonModule, MatIconModule, MatFormFieldModule, MatInputModule, FormsModule], imports: [CommonModule, TranslateModule, MatButtonModule, MatIconModule, MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule],
selector: 'app-search-input-control', selector: 'app-search-input-control',
templateUrl: './search-input-control.component.html', templateUrl: './search-input-control.component.html',
styleUrls: ['./search-input-control.component.scss'], styleUrls: ['./search-input-control.component.scss'],
encapsulation: ViewEncapsulation.None, encapsulation: ViewEncapsulation.None,
host: { class: 'app-search-control' } host: { class: 'app-search-control' }
}) })
export class SearchInputControlComponent { export class SearchInputControlComponent implements OnInit {
private readonly destroyRef = inject(DestroyRef);
/** Type of the input field to render, e.g. "search" or "text" (default). */ /** Type of the input field to render, e.g. "search" or "text" (default). */
@Input() @Input()
inputType = 'text'; inputType = 'text';
@ -63,14 +66,27 @@ export class SearchInputControlComponent {
@ViewChild('searchInput', { static: true }) @ViewChild('searchInput', { static: true })
searchInput: ElementRef; searchInput: ElementRef;
searchTerm = ''; searchFieldFormControl = new FormControl('');
searchSubmit(event: any) { get searchTerm(): string {
this.submit.emit(event); return this.searchFieldFormControl.value.replace('text:', 'TEXT:');
} }
inputChange(event: any) { set searchTerm(value: string) {
this.searchChange.emit(event); this.searchFieldFormControl.setValue(value);
}
ngOnInit() {
this.searchFieldFormControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((searchTermValue) => {
this.searchFieldFormControl.markAsTouched();
this.searchChange.emit(searchTermValue);
});
}
searchSubmit() {
if (!this.searchFieldFormControl.errors) {
this.submit.emit(this.searchTerm);
}
} }
clear() { clear() {