پیاده سازی جستجوی بر روی این گرید، شامل موارد زیر است:
اضافه کردن دو خاصیت جدید به کلاس PagedQueryModel سمت کلاینت جهت مشخص سازی ستونی که قرار است بر روی آن جستجو انجام شود و همچنین مقدار آن:
export class PagedQueryModel {
constructor(
// ...
public filterByColumn: string,
public filterByValue: string,
) { }
}
سپس به ProductsListComponent دو متد زیر را اضافه میکنیم:
doFilter() {
this.queryModel.page = 1;
this.getPagedProductsList();
}
resetFilter() {
this.queryModel.page = 1;
this.queryModel.filterByColumn = "";
this.queryModel.filterByValue = "";
this.getPagedProductsList();
}
اولی کار جستجو را انجام میدهد و دومی بازگشت حالت گرید به وضعیت اول آن است. متد getPagedProductsList قابلیت واکشی خودکار اطلاعات دو خاصیت جدیدی را که اضافه کردیم دارد و نیازی به تنظیمات اضافهتری ندارد. یعنی filterByColumn و filterByValue را به صورت خودکار به سمت سرور ارسال میکند.
پس از آن، قالب این گرید (products-list.component.html) جهت افزودن جستجو، به صورت زیر تغییر میکند:
<div class="panel panel-default">
<div class="panel-body">
<div class="form-group">
<input type="text" [(ngModel)]="queryModel.filterByValue" placeholder="Search For ..."
class="form-control" />
</div>
<div class="form-group">
<select class="form-control" name="filterColumn" [(ngModel)]="queryModel.filterByColumn">
<option value="">Filter by ...</option>
<option *ngFor="let column of columns" [value]="column.propertyName">
{{ column.title }}
</option>
</select>
</div>
<button class="btn btn-primary" type="button" (click)="doFilter()">Search</button>
<button class="btn btn-default" type="button" (click)="resetFilter()">Reset</button>
</div>
</div>
که در آن queryModel.filterByColumn و queryModel.filterByValue از کاربر دریافت میشوند. همچنین دو متد doFilter و resetFilter را نیز فراخوانی میکند.
با این شکل:
تغییرات سمت سرور آن نیز به صورت ذیل است:
ابتدا IPagedQueryModel را با همان دو خاصیت جدید ستون فیلتر شونده و مقدار آن، تکمیل میکنیم:
public interface IPagedQueryModel
{
// ....
string FilterByColumn { get; set; }
string FilterByValue { get; set; }
}
public class ProductQueryViewModel : IPagedQueryModel
{
// ... other properties ...
// ...
public string FilterByColumn { get; set; }
public string FilterByValue { get; set; }
}
از این دو خاصیت جدید، جهت افزودن متد اعمال جستجو، همانند متد ApplyOrdering که پیشتر تعریف شد، استفاده میکنیم:
public static class IQueryableExtensions
{
public static IQueryable<T> ApplyFiltering<T>(
this IQueryable<T> query,
IPagedQueryModel model,
IDictionary<string, Expression<Func<T, object>>> columnsMap)
{
if (string.IsNullOrWhiteSpace(model.FilterByValue) || !columnsMap.ContainsKey(model.FilterByColumn))
{
return query;
}
var func = columnsMap[model.FilterByColumn].Compile();
return query.Where(x => func(x).ToString() == model.FilterByValue);
}
در اینجا همان columnsMap مورد استفاده در متد ApplyOrdering جهت نگاشت نامهای رشتهای ستونها به معادل Expression آنها استفاده شدهاست.
در آخر، به کنترلر ProductController و اکشن متد GetPagedProducts آن مراجعه کرده و پیش از ApplyOrdering، متد جدید ApplyFiltering فوق را اضافه میکنیم:
var columnsMap = new Dictionary<string, Expression<Func<Product, object>>>()
{
["productId"] = p => p.ProductId,
["productName"] = p => p.ProductName,
["isAvailable"] = p => p.IsAvailable,
["price"] = p => p.Price
};
query = query.ApplyFiltering(queryModel, columnsMap);
query = query.ApplyOrdering(queryModel, columnsMap);
کدهای کامل این تغییرات را از اینجا میتوانید دریافت کنید.