Angular 简化排序的指令
Angular directive to simplify sorting
我有 list/table 个人,我可以按名字、姓氏等排序
当我点击标题(比如名字)时,它会使用查询字符串参数进行路由
?sort=firstname
,如果我再次点击它,它会将参数更改为
?sort=firstname-desc
。同时,我需要一个图标来显示参数旁边的向上或向下箭头,表示升序或降序排序。这是一个非常标准的排序场景。
我当前的模板如下所示:
<div class="heading">
First name
<a [routerLink] [queryParams]="sortParams('firstname')">
<img src="assets/icons/icon-sort-down.svg" class="icon-normal" [class.flip]="showFlip('firstname')">
</a>
</div>
这工作正常,因为我在组件中有一些逻辑来处理 sortParams
和 showFlip
但我想简化它,所以我可以轻松地将相同的逻辑添加到多个字段,在多个视图上,不需要额外的重复组件逻辑。
创建指令似乎是可行的方法,但是当我创建指令时,我通常只使用 @HostBinding
修改 dom 属性。怎么可能写一个指令(称之为排序)来让我像这样定义模板:
<div class="heading">
First name
<a [sorting]="'firstname'"></a>
</div>
该指令需要修改 a 标签以包含 routerLink
和 queryParams
,以及添加一些 non-static 模板内容。我知道我可以在我的指令中注入 ViewContainerRef
,但是从那里,我的指令知识需要一些帮助。
请试试这个:
import {Directive, Input} from '@angular/core';
import {YourSortingService} from 'YouServiceFileLocation';
@Directive({
selector:'[sorting]'
})
export SortingDirective{
@Input() sortingQueryString:string;
constructor(private sortingService:YourSortingService){}
@HostBinding('click')
private onClick(){
//On click on the <a> tag
this.sortingService.get(`url?sort=${this.sortingQueryString}`);
}
}
你可以这样使用它:
<div class="heading">
First name
<a sorting [sortingQueryString]="'firstname'"></a>
</div>
好的,所以我发现写一个指令来解决这个问题是个坏主意。我真正需要的只是一个包装逻辑的组件。
我几乎得到了我想要的 markup/template。实际上,我本可以像我设定的那样把它做得很好,但决定不让组件进行路由器解析,而是将查询字符串排序参数解析给组件,以便它对其进行最终处理。
<div class="heading">
First name
<fd-sorting-header [fieldName]="'firstname'" [sort]="sort"></fd-sorting-header>
</div>
所以我创建了一个组件来解析排序查询字符串和设置 routerLink/queryParams。组件模板最终是这样的:
<a [routerLink] [queryParams]="sortParams"><img src="assets/icons/icon-sort-down.svg" class="icon-normal" [class.flip]="showFlip"></a>
还有一个简单的 class 像这样:
export class SortingHeaderComponent {
public sortParams: any;
public showFlip: boolean;
@Input('fieldName') fieldName: string;
@Input('sort')
set sort(sort: string) {
const [column, dir] = (sort || '').split('-');
const direction = (dir && dir.toLowerCase() === 'desc') ? 'desc' : 'asc';
this.showFlip = column === this.fieldName && direction !== 'desc';
this.sortParams = { sort: this.fieldName + ((this.showFlip) ? '-desc' : '') };
}
constructor() { }
}
我有 list/table 个人,我可以按名字、姓氏等排序
当我点击标题(比如名字)时,它会使用查询字符串参数进行路由
?sort=firstname
,如果我再次点击它,它会将参数更改为
?sort=firstname-desc
。同时,我需要一个图标来显示参数旁边的向上或向下箭头,表示升序或降序排序。这是一个非常标准的排序场景。
我当前的模板如下所示:
<div class="heading">
First name
<a [routerLink] [queryParams]="sortParams('firstname')">
<img src="assets/icons/icon-sort-down.svg" class="icon-normal" [class.flip]="showFlip('firstname')">
</a>
</div>
这工作正常,因为我在组件中有一些逻辑来处理 sortParams
和 showFlip
但我想简化它,所以我可以轻松地将相同的逻辑添加到多个字段,在多个视图上,不需要额外的重复组件逻辑。
创建指令似乎是可行的方法,但是当我创建指令时,我通常只使用 @HostBinding
修改 dom 属性。怎么可能写一个指令(称之为排序)来让我像这样定义模板:
<div class="heading">
First name
<a [sorting]="'firstname'"></a>
</div>
该指令需要修改 a 标签以包含 routerLink
和 queryParams
,以及添加一些 non-static 模板内容。我知道我可以在我的指令中注入 ViewContainerRef
,但是从那里,我的指令知识需要一些帮助。
请试试这个:
import {Directive, Input} from '@angular/core';
import {YourSortingService} from 'YouServiceFileLocation';
@Directive({
selector:'[sorting]'
})
export SortingDirective{
@Input() sortingQueryString:string;
constructor(private sortingService:YourSortingService){}
@HostBinding('click')
private onClick(){
//On click on the <a> tag
this.sortingService.get(`url?sort=${this.sortingQueryString}`);
}
}
你可以这样使用它:
<div class="heading">
First name
<a sorting [sortingQueryString]="'firstname'"></a>
</div>
好的,所以我发现写一个指令来解决这个问题是个坏主意。我真正需要的只是一个包装逻辑的组件。
我几乎得到了我想要的 markup/template。实际上,我本可以像我设定的那样把它做得很好,但决定不让组件进行路由器解析,而是将查询字符串排序参数解析给组件,以便它对其进行最终处理。
<div class="heading">
First name
<fd-sorting-header [fieldName]="'firstname'" [sort]="sort"></fd-sorting-header>
</div>
所以我创建了一个组件来解析排序查询字符串和设置 routerLink/queryParams。组件模板最终是这样的:
<a [routerLink] [queryParams]="sortParams"><img src="assets/icons/icon-sort-down.svg" class="icon-normal" [class.flip]="showFlip"></a>
还有一个简单的 class 像这样:
export class SortingHeaderComponent {
public sortParams: any;
public showFlip: boolean;
@Input('fieldName') fieldName: string;
@Input('sort')
set sort(sort: string) {
const [column, dir] = (sort || '').split('-');
const direction = (dir && dir.toLowerCase() === 'desc') ? 'desc' : 'asc';
this.showFlip = column === this.fieldName && direction !== 'desc';
this.sortParams = { sort: this.fieldName + ((this.showFlip) ? '-desc' : '') };
}
constructor() { }
}