طراحی یک گرید با Angular و ASP.NET Core - قسمت دوم - پیاده سازی سمت کلاینت
نویسنده: وحید نصیری
تاریخ: ۱۳۹۶/۰۴/۳۱ ۱۱:۳۵
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
> npm install bootstrap --save > npm install ngx-bootstrap --save
"apps": [
{
"styles": [
"../node_modules/bootstrap/dist/css/bootstrap.min.css",
"styles.css"
], import { PaginationModule } from "ngx-bootstrap";
@NgModule({
imports: [
PaginationModule.forRoot()
] >ng g m SimpleGrid -m app.module --routing
>ng g c SimpleGrid/products-list
>ng g cl SimpleGrid/app-product
export class AppProduct {
constructor(
public productId: number,
public productName: string,
public price: number,
public isAvailable: boolean
) {}
} >ng g cl SimpleGrid/PagedQueryModel
export class PagedQueryModel {
constructor(
public sortBy: string,
public isAscending: boolean,
public page: number,
public pageSize: number
) {}
} >ng g cl SimpleGrid/PagedQueryResult
export class PagedQueryResult<T> {
constructor(public totalItems: number, public items: T[]) {}
} >ng g cl SimpleGrid/GridColumn
export class GridColumn {
constructor(
public title: string,
public propertyName: string,
public isSortable: boolean
) {}
} >ng g s SimpleGrid/products-list -m simple-grid.module
toQueryString(obj: any): string {
const parts = [];
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
if (value !== null && value !== undefined) {
parts.push(encodeURIComponent(key) + "=" + encodeURIComponent(value));
}
}
}
return parts.join("&");
} [HttpGet("[action]")]
public PagedQueryResult<Product> GetPagedProducts(ProductQueryViewModel queryModel) http://localhost:5000/api/Product/GetPagedProducts?sortBy=productId&isAscending=true&page=2&pageSize=7
@Injectable()
export class ProductsListService {
private baseUrl = "api/Product";
constructor(private http: Http) {}
getPagedProductsList(
queryModel: PagedQueryModel
): Observable<PagedQueryResult<AppProduct>> {
return this.http
.get(`${this.baseUrl}/GetPagedProducts?${this.toQueryString(queryModel)}`)
.map(res => {
const result = res.json();
return new PagedQueryResult<AppProduct>(
result.totalItems,
result.items
);
});
}
<table class="table table-striped table-hover table-bordered table-condensed">
<thead>
<tr>
<th class="text-center" style="width:3%">#</th>
<th *ngFor="let column of columns" class="text-center">
<div *ngIf="column.isSortable" (click)="sortBy(column.propertyName)" style="cursor: pointer">
{{ column.title }}
<i *ngIf="queryModel.sortBy === column.propertyName" class="glyphicon"
[class.glyphicon-sort-by-order]="queryModel.isAscending" [class.glyphicon-sort-by-order-alt]="!queryModel.isAscending"></i>
</div>
<div *ngIf="!column.isSortable" style="cursor: pointer">
{{ column.title }}
</div>
</th>
</tr>
</thead> export class ProductsListComponent implements OnInit {
columns: GridColumn[] = [
new GridColumn("Id", "productId", true),
new GridColumn("Name", "productName", true),
new GridColumn("Price", "price", true),
new GridColumn("Available", "isAvailable", true)
]; export class ProductsListComponent implements OnInit {
itemsPerPage = 7;
queryModel = new PagedQueryModel("productId", true, 1, this.itemsPerPage);
sortBy(columnName) {
if (this.queryModel.sortBy === columnName) {
this.queryModel.isAscending = !this.queryModel.isAscending;
} else {
this.queryModel.sortBy = columnName;
this.queryModel.isAscending = true;
}
this.getPagedProductsList();
}
} <tbody>
<tr *ngFor="let item of queryResult.items; let i = index">
<td class="text-center">{{ itemsPerPage * (currentPage - 1) + i + 1 }}</td>
<td class="text-center">{{ item.productId }}</td>
<td class="text-center">{{ item.productName }}</td>
<td class="text-center">{{ item.price | number:'.0' }}</td>
<td class="text-center">
<input id="item-{{ item.productId }}" type="checkbox" [checked]="item.isAvailable"
disabled="disabled" />
</td>
</tr>
</tbody>
</table> export class ProductsListComponent implements OnInit {
itemsPerPage = 7;
currentPage: number;
numberOfPages: number;
isLoading = false;
queryModel = new PagedQueryModel("productId", true, 1, this.itemsPerPage);
queryResult = new PagedQueryResult<AppProduct>(0, []);
constructor(private productsListService: ProductsListService) {}
ngOnInit() {
this.getPagedProductsList();
}
private getPagedProductsList() {
this.isLoading = true;
this.productsListService
.getPagedProductsList(this.queryModel)
.subscribe(result => {
this.queryResult = result;
this.isLoading = false;
});
}
}
<div align="center">
<pagination [maxSize]="8" [boundaryLinks]="true" [totalItems]="queryResult.totalItems"
[rotate]="false" previousText="‹" nextText="›" firstText="«"
lastText="»" (numPages)="numberOfPages = $event" [(ngModel)]="currentPage"
(pageChanged)="onPageChange($event)"></pagination>
</div>
<pre class="card card-block card-header">Page: {{currentPage}} / {{numberOfPages}}</pre> export class ProductsListComponent implements OnInit {
itemsPerPage = 7;
currentPage: number;
numberOfPages: number;
onPageChange(event: any) {
this.queryModel.page = event.page;
this.getPagedProductsList();
}
} export class PagedQueryModel {
constructor(
// ...
public filterByColumn: string,
public filterByValue: string,
) { }
} doFilter() {
this.queryModel.page = 1;
this.getPagedProductsList();
}
resetFilter() {
this.queryModel.page = 1;
this.queryModel.filterByColumn = "";
this.queryModel.filterByValue = "";
this.getPagedProductsList();
} <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>
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; }
} 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);
} 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); 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().Contains( model.FilterByValue.Trim()));
} var func = columnsMap[model.FilterByColumn].Compile();
{Method = <Internal Error evaluating expression>} 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 predicate = string.Format("{0} {1} @{2}", model.FilterByColumn, "==", 0);
return query.Where(predicate, model.FilterByValue);
} <ItemGroup>
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.1.2" />
</ItemGroup> export class AppProduct {
constructor(
public productId: number,
public productName: string,
public price: number,
public isAvailable: boolean
) {}
} export class AppProduct {
public productId: number;
public productName: string;
public price: number;
public isAvailable: boolean;
} export interface AppProduct {
productId: number;
productName: string;
price: number;
isAvailable: boolean;
} Consider using a class instead of an interface for services and declarables (components, directives, and pipes)
Consider using an interface for data models
البته این مورد موافقها و مخالفهایی هم دارد.interface student {
name: string,
phone: any
} student = {
name :'hasan',
phone :123
}
constructor() {} model: studnet= {} as any;
constructor() {
model.name='hasan';
model.phone =123;
} let params = new HttpParams();
if(sortBy != null && isAscending != null && page != null && pageSize != null) {
params = params.append('sortBy');
params = params.append('isAscending');
params = params.append('page');
params = params.append('pageSize');
} getPagedProductsList(sortBy?,isAscending?,
page?,pageSize?):Observable<PagedQueryResult<AppProduct>> {
let params = new HttpParams();
if(sortBy != null && isAscending != null && page != null && pageSize != null)
{
params = params.append('sortBy');
params = params.append('isAscending');
params = params.append('page');
params = params.append('pageSize');
}
return this.http.get(`${this.baseUrl}/GetPagedProducts , {params})
.map(res => {
const result = res.json();
return new PagedQueryResult<AppProduct>(
result.totalItems,
result.items
);
});
}