Skip to content

Commit

Permalink
[ACS-8998] Added validation to search input to disallow certain speci…
Browse files Browse the repository at this point in the history
…al 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
  • Loading branch information
swapnil-verma-gl authored Dec 18, 2024
1 parent 07d0203 commit 111f3f9
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
mat-icon-button
matPrefix
class="app-search-button"
(click)="searchSubmit(searchTerm)"
(click)="searchSubmit()"
[title]="'SEARCH.BUTTON.TOOLTIP' | translate"
>
<mat-icon [attr.aria-label]="'SEARCH.BUTTON.ARIA-LABEL' | translate">search</mat-icon>
Expand All @@ -17,15 +17,14 @@
[attr.aria-label]="'SEARCH.INPUT.ARIA-LABEL' | translate"
[type]="inputType"
id="app-control-input"
[(ngModel)]="searchTerm"
(ngModelChange)="inputChange($event)"
(keyup.enter)="searchSubmit($event)"
[formControl]="searchFieldFormControl"
(keyup.enter)="searchSubmit()"
[placeholder]="'SEARCH.INPUT.PLACEHOLDER' | translate"
autocomplete="off"
/>
<div matSuffix>
<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>
</div>
</mat-form-field>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,31 +43,29 @@ describe('SearchInputControlComponent', () => {
});

it('should emit submit event on searchSubmit', () => {
const keyboardEvent = { target: { value: 'a' } };
component.searchTerm = 'mock-search-term';

let eventArgs = null;
component.submit.subscribe((args) => (eventArgs = args));
let submittedSearchTerm = '';
component.submit.subscribe((searchTerm) => (submittedSearchTerm = searchTerm));

component.searchSubmit(keyboardEvent);
expect(eventArgs).toBe(keyboardEvent);
component.searchSubmit();
expect(submittedSearchTerm).toBe('mock-search-term');
});

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;
component.searchChange.subscribe((args) => (eventArgs = args));

component.inputChange(searchTerm);
expect(eventArgs).toBe(searchTerm);
expect(emittedSearchTerm).toBe('mock-search-term');
});

it('should emit searchChange event on clear', () => {
let eventArgs = null;
component.searchChange.subscribe((args) => (eventArgs = args));
let emittedSearchTerm: string = null;
component.searchChange.subscribe((searchTerm) => (emittedSearchTerm = searchTerm));

component.clear();
expect(eventArgs).toBe('');
expect(emittedSearchTerm).toBe('');
});

it('should clear searchTerm', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,28 @@
* 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 { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatFormFieldModule } from '@angular/material/form-field';
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({
standalone: true,
imports: [CommonModule, TranslateModule, MatButtonModule, MatIconModule, MatFormFieldModule, MatInputModule, FormsModule],
imports: [CommonModule, TranslateModule, MatButtonModule, MatIconModule, MatFormFieldModule, MatInputModule, FormsModule, ReactiveFormsModule],
selector: 'app-search-input-control',
templateUrl: './search-input-control.component.html',
styleUrls: ['./search-input-control.component.scss'],
encapsulation: ViewEncapsulation.None,
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). */
@Input()
inputType = 'text';
Expand All @@ -63,14 +66,27 @@ export class SearchInputControlComponent {
@ViewChild('searchInput', { static: true })
searchInput: ElementRef;

searchTerm = '';
searchFieldFormControl = new FormControl('');

get searchTerm(): string {
return this.searchFieldFormControl.value.replace('text:', 'TEXT:');
}

set searchTerm(value: string) {
this.searchFieldFormControl.setValue(value);
}

searchSubmit(event: any) {
this.submit.emit(event);
ngOnInit() {
this.searchFieldFormControl.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((searchTermValue) => {
this.searchFieldFormControl.markAsTouched();
this.searchChange.emit(searchTermValue);
});
}

inputChange(event: any) {
this.searchChange.emit(event);
searchSubmit() {
if (!this.searchFieldFormControl.errors) {
this.submit.emit(this.searchTerm);
}
}

clear() {
Expand Down

0 comments on commit 111f3f9

Please sign in to comment.