Web Components 그리드 검색 필터
The Ignite UI for Web Components Search Filter feature in Web Components Grid enables the process of finding values in the collection of data. We make it easier to set up this functionality and it can be implemented with a search input box, buttons, keyboard navigation and other useful features for an even better user experience. While browsers natively provide content search functionality, most of the time the IgcGridComponent virtualizes its columns and rows that are out of view. In these cases, the native browser search is unable to search data in the virtualized cells, since they are not part of the DOM. We have extended the Web Components Material table-based grid with a search API that allows you to search through the virtualized content of the IgcGridComponent.
Web Components Search Example
The following example represents IgcGridComponent with search input box that allows searching in all columns and rows, as well as specific filtering options for each column.
Web Components Search Usage
Grid Setup
그리드를 생성하고 이를 데이터에 바인딩하는 것부터 시작해 보겠습니다. 또한 우리가 사용할 구성 요소에 대한 몇 가지 사용자 정의 스타일을 추가할 것입니다!
.gridSize {
--ig-size: var(--ig-size-small);
}
<igc-grid id="grid1" class="gridSize" auto-generate="false" allow-filtering="true">
<igc-column field="IndustrySector" data-type="string" sortable="true"></igc-column>
<igc-column field="IndustryGroup" data-type="string" sortable="true"></igc-column>
<igc-column field="SectorType" data-type="string" sortable="true"></igc-column>
<igc-column field="KRD" data-type="number" sortable="true"></igc-column>
<igc-column field="MarketNotion" data-type="number" sortable="true"></igc-column>
<igc-column field="Date" data-type="date" sortable="true"></igc-column>
</igc-grid>
Great, and now let's prepare for the search API of our IgcGridComponent! We can create a few properties, which can be used for storing the currently searched text and whether the search is case sensitive and/or by an exact match.
private grid: IgcGridComponent;
private searchBox: IgcInputComponent;
private searchIcon: IgcIconComponent;
private clearIcon: IgcIconComponent;
private nextIconButton: IgcIconButtonComponent;
private prevIconButton: IgcIconButtonComponent;
private caseSensitiveChip: IgcChipComponent;
private exactMatchChip: IgcChipComponent;
Web Components Search Box Input
Now let's create our search input! By getting the input element we can get its current value. This will allow us to use the IgcGridComponent's findNext and findPrev methods to highlight all the occurrences of the SearchText and scroll to the next/previous one (depending on which method we have invoked).
Both the findNext and the findPrev methods have three arguments:
Text: string (the text we are searching for)- (optional)
CaseSensitive: boolean (should the search be case sensitive or not, default value is false) - (optional)
ExactMatch: boolean (should the search be by an exact match or not, default value is false)
When searching by an exact match, the search API will highlight as results only the cell values that match entirely the SearchText by taking the case sensitivity into account as well. For example the strings 'software' and 'Software' are an exact match with a disregard for the case sensitivity.
The methods from above return a number value (the number of times the IgcGridComponent contains the given string).
<igc-input id="searchBox" name="searchBox">
</igc-input>
constructor() {
var grid = this.grid = document.getElementById('grid') as IgcGridComponent;
this.searchBox = document.getElementById('searchBox') as IgcInputComponent;
grid.data = new MarketData();
}
public nextSearch(){
this.grid.findNext(this.searchBox.value, false, false);
}
Add Search Buttons
In order to freely search and navigate among our search results, let's create a couple of buttons by invoking the findNext and the findPrev methods inside the buttons' respective click event handlers.
<igc-icon-button id="prevIconBtn" variant="flat" name="prev" collection="material" ></igc-icon-button>
<igc-icon-button id="nextIconBtn" variant="flat" name="next" collection="material"></igc-icon-button>
constructor() {
var nextIconButton = document.getElementById('nextIconBtn') as IgcIconButtonComponent;
var prevIconButton = document.getElementById('prevIconBtn') as IgcIconButtonComponent;
nextIconButton.addEventListener("click", this.nextSearch);
prevIconButton.addEventListener("click", this.prevSearch);
}
public prevSearch() {
this.grid.findPrev(this.searchBox.value, this.caseSensitiveChip.selected, this.exactMatchChip.selected);
}
public nextSearch() {
this.grid.findNext(this.searchBox.value, this.caseSensitiveChip.selected, this.exactMatchChip.selected);
}
Add Keyboard Search
We can also allow the users to navigate the results by using the keyboard's arrow keys and the ENTER key. In order to achieve this, we can handle the keydown event of our search input by preventing the default caret movement of the input with the PreventDefault method and invoke the findNext/findPrev methods depending on which key the user has pressed.
<input id="searchBox" name="searchBox"/>
constructor() {
searchBox.addEventListener("keydown", (evt) => { this.onSearchKeydown(evt); });
this.searchBox.addEventListener("igcInput", (evt) => {
this.searchIcon.name = evt.detail ? 'clear' : 'search';
this.grid.findNext(evt.detail, this.caseSensitiveChip.selected, this.exactMatchChip.selected);
});
}
public onSearchKeydown(evt: KeyboardEvent) {
if (evt.key === 'Enter' || evt.key === 'ArrowDown') {
evt.preventDefault();
this.grid.findNext(this.searchBox.value, this.caseSensitiveChip.selected, this.exactMatchChip.selected);
} else if (evt.key === 'ArrowUp') {
evt.preventDefault();
this.grid.findPrev(this.searchBox.value, this.caseSensitiveChip.selected, this.exactMatchChip.selected);
}
}
}
Case Sensitive and Exact Match
Now let's allow the user to choose whether the search should be case sensitive and/or by an exact match. For this purpose we can use simple checkbox inputs and bind to its change event where we can use the checkbox checked state.
<span>Case sensitive</span>
<input id="case" type="checkbox">
<span>Exact match</span>
<input id="exact" type="checkbox">
constructor() {
const case = document.getElementById("case") as HTMLInputElement;
const exact = document.getElementById("exact") as HTMLInputElement;
case.addEventListener("change", this.updateSearch);
exact.addEventListener("change", this.updateSearch);
}
public updateSearch() {
const search1 = document.getElementById("search1") as HTMLInputElement;
const case = document.getElementById("case") as HTMLInputElement;
const exact = document.getElementById("exact") as HTMLInputElement;
const grid = document.getElementById("grid") as IgcGridComponent;
grid.findNext(search1.value, case.checked, exact.checked);
}
Persistence
What if we would like to filter and sort our IgcGridComponent or even to add and remove records? After such operations, the highlights of our current search automatically update and persist over any text that matches the SearchText! Furthermore, the search will work with paging and will persist the highlights through changes of the IgcGridComponent's PerPage property.
Adding icons
다른 구성 요소 중 일부를 사용하여 풍부한 사용자 인터페이스를 만들고 전체 검색 창의 전반적인 디자인을 개선할 수 있습니다! 검색 입력 왼쪽에 멋진 검색 또는 삭제 아이콘, 검색 옵션을 위한 몇 개의 칩, 오른쪽 탐색을 위한 멋진 리플 스타일 버튼과 결합된 일부 재료 디자인 아이콘을 가질 수 있습니다.
import { defineComponents, IgcInputComponent, IgcChipComponent, IgcIconComponent, IgcIconButtonComponent, registerIconFromText } from "igniteui-webcomponents";
defineComponents(IgcInputComponent, IgcChipComponent, IgcIconComponent, IgcIconButtonComponent);
마지막으로 템플릿을 새로운 구성요소로 업데이트해 보겠습니다.
<igx-input-group type="search" class="offset">
<igx-prefix>
<igx-icon *ngIf="searchText.length == 0">search</igx-icon>
<igx-icon *ngIf="searchText.length > 0" (click)="clearSearch()">clear</igx-icon>
</igx-prefix>
<input #search1 id="search1" igxInput placeholder="Search" [(ngModel)]="searchText" (ngModelChange)="@@igObjectRef.findNext(searchText, caseSensitive, exactMatch)"
(keydown)="searchKeyDown($event)" />
<igx-suffix *ngIf="searchText.length > 0">
</igx-suffix>
</igx-input-group>
<igc-input id="searchBox" name="searchBox">
<igc-icon id="searchIcon" slot="prefix" name="search" collection="material"></igc-icon>
<div slot="suffix">
<igc-chip selectable="true" id="caseSensitiveChip">Case Sensitive</igc-chip>
<igc-chip selectable="true" id="exactMatchChip">Exact Match</igc-chip>
</div>
<div slot="suffix">
<igc-icon-button id="prevIconBtn" variant="flat" name="prev" collection="material" ></igc-icon-button>
<igc-icon-button id="nextIconBtn" variant="flat" name="next" collection="material"></igc-icon-button>
</div>
</igc-input>
constructor() {
const prevIconText = "<svg width='24' height='24' viewBox='0 0 24 24'><path d='M15.41 7.41 14 6l-6 6 6 6 1.41-1.41L10.83 12z'></path></svg>";
const nextIconText = "<svg width='24' height='24' viewBox='0 0 24 24'><path d='M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z'></path></svg>";
const clearIconText = "<svg width='24' height='24' viewBox='0 0 24 24' title='Clear'><path d='M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'></path></svg>";
const searchIconText = "<svg width='24' height='24' viewBox='0 0 24 24'><path d='M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z' /></svg>";
registerIconFromText("prev", prevIconText, "material");
registerIconFromText("next", nextIconText, "material");
registerIconFromText("clear", clearIconText, "material");
registerIconFromText("search", searchIconText, "material");
}
입력 그룹 오른쪽에 다음 목적을 가진 세 개의 별도 컨테이너를 만들어 보겠습니다.
- For displaying a couple of chips that toggle the
CaseSensitiveand theExactMatchproperties. We have replaced the checkboxes with two stylish chips. Whenever a chip is clicked, we invoke its respective handler.
<div slot="suffix">
<igc-chip selectable="true" id="caseSensitiveChip">Case Sensitive</igc-chip>
<igc-chip selectable="true" id="exactMatchChip">Exact Match</igc-chip>
</div>
constructor() {
const input = document.getElementById("searchBox") as IgcInputComponent;
input.addEventListener("change", this.updateSearch);
}
public updateSearch() {
const grid = document.getElementById('grid') as IgcGridComponent;
const caseSensitiveChip = document.getElementById('caseSensitiveChip') as IgcChipComponent;
const exactMatchChip = document.getElementById('exactMatchChip') as IgcChipComponent;
grid.findNext(input.value, caseSensitiveChip.selected, exactMatchChip.selected);
}
- For the search navigation buttons, we have added two ripple styled buttons with material icons. The handlers for the click events remain the same - invoking the
findNext/findPrevmethods.
<div slot="suffix">
<igc-icon-button id="prevIconBtn" variant="flat" name="prev" collection="material" ></igc-icon-button>
<igc-icon-button id="nextIconBtn" variant="flat" name="next" collection="material"></igc-icon-button>
</div>
constructor() {
const nextIconButton = this.nextIconButton = document.getElementById('nextIconBtn') as IgcIconButtonComponent;
const prevIconButton = this.prevIconButton = document.getElementById('prevIconBtn') as IgcIconButtonComponent;
nextIconButton.addEventListener("click", this.nextSearch);
prevIconButton.addEventListener("click", this.prevSearch);
}
public nextSearch() {
this.grid.findNext(this.searchBox.value, this.caseSensitiveChip.selected, this.exactMatchChip.selected);
}
public prevSearch() {
this.grid.findPrev(this.searchBox.value, this.caseSensitiveChip.selected, this.exactMatchChip.selected);
}
Known Limitations
| 한정 | 설명 |
|---|---|
| 템플릿을 사용하여 셀에서 검색 | 검색 기능 강조 표시는 기본 셀 템플릿에서만 작동합니다. 사용자 정의 셀 템플릿이 포함된 열이 있는 경우 강조 표시가 작동하지 않으므로 열 포맷터와 같은 대체 접근 방식을 사용하거나searchable 열의 속성을 false로 설정합니다. |
| 원격 가상화 | 원격 가상화를 사용하면 검색이 제대로 작동하지 않습니다. |
| 텍스트가 잘린 셀 | 셀의 텍스트가 너무 커서 맞지 않고 찾고 있는 텍스트가 줄임표로 잘려도 셀로 스크롤하여 일치 횟수에 포함시키지만 아무것도 강조 표시되지 않습니다. |
API References
In this article we implemented our own search bar for the IgcGridComponent with some additional functionality when it comes to navigating between the search results. We also used some additional Ignite UI for Web Components components like icons, chips and inputs. The search API is listed below.
IgcGridComponent methods:
IgcColumnComponent properties:
사용된 관련 API가 포함된 추가 구성요소:
Additional Resources
우리 커뮤니티는 활동적이며 항상 새로운 아이디어를 환영합니다.