• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

atinc / ngx-tethys / c0ef8457-a839-451f-8b72-80fd73106231

02 Apr 2024 02:27PM UTC coverage: 90.524% (-0.06%) from 90.585%
c0ef8457-a839-451f-8b72-80fd73106231

Pull #3062

circleci

minlovehua
refactor(all): use the transform attribute of @Input() instead of @InputBoolean() and @InputNumber()
Pull Request #3062: refactor(all): use the transform attribute of @input() instead of @InputBoolean() and @InputNumber()

4987 of 6108 branches covered (81.65%)

Branch coverage included in aggregate %.

217 of 223 new or added lines in 82 files covered. (97.31%)

202 existing lines in 53 files now uncovered.

12246 of 12929 relevant lines covered (94.72%)

1055.59 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.83
/src/tree/tree-node.component.ts
1
import { Subject } from 'rxjs';
2
import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
3
import {
4
    ChangeDetectorRef,
5
    Component,
6
    ContentChild,
7
    ElementRef,
8
    EventEmitter,
9
    HostBinding,
10
    Inject,
11
    Input,
12
    NgZone,
13
    OnChanges,
1✔
14
    OnDestroy,
15
    OnInit,
16
    Output,
17
    SimpleChanges,
18
    TemplateRef,
19
    ViewChild,
1✔
20
    ViewEncapsulation,
21
    booleanAttribute,
199✔
22
    numberAttribute
23
} from '@angular/core';
UNCOV
24

×
25
import { THY_TREE_ABSTRACT_TOKEN, ThyTreeAbstractComponent } from './tree-abstract';
26
import { ThyTreeNode } from './tree-node.class';
27
import { ThyTreeEmitEvent, ThyTreeNodeCheckState, ThyClickBehavior } from './tree.class';
623✔
28
import { ThyTreeService } from './tree.service';
623✔
29
import { ThyLoading } from 'ngx-tethys/loading';
623✔
30
import { ThyIcon } from 'ngx-tethys/icon';
623✔
31
import { NgIf, NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
623✔
32

623✔
33
const passiveEventListenerOptions = <AddEventListenerOptions>normalizePassiveListenerOptions({ passive: true });
623✔
34

623✔
35
/**
623✔
36
 * 树形控件的节点组件
623✔
37
 * @private
623✔
38
 * @name thy-tree-node
623✔
39
 */
623✔
40
@Component({
623✔
41
    selector: 'thy-tree-node',
623✔
42
    templateUrl: './tree-node.component.html',
43
    encapsulation: ViewEncapsulation.None,
44
    standalone: true,
7✔
45
    imports: [NgIf, ThyIcon, NgClass, NgStyle, NgTemplateOutlet, ThyLoading]
2✔
46
})
47
export class ThyTreeNodeComponent implements OnDestroy, OnInit, OnChanges {
48
    /**
5✔
49
     * node 节点展现所需的数据
2✔
50
     */
51
    @Input() node: ThyTreeNode;
52

3✔
53
    /**
1✔
54
     * 设置 TreeNode 是否支持异步加载
55
     */
56
    @Input({ transform: booleanAttribute }) thyAsync = false;
2✔
57

58
    /**
59
     * 设置 TreeNode 是否支持多选节点
60
     */
7✔
61
    @Input({ transform: booleanAttribute }) thyMultiple = false;
62

63
    /**
64
     * 设置 TreeNode 是否支持拖拽排序
65
     */
66
    @Input({ transform: booleanAttribute }) thyDraggable = false;
67

1✔
68
    /**
69
     * 设置 TreeNode 是否支持 Checkbox 选择
70
     */
71
    @Input({ transform: booleanAttribute }) thyCheckable = false;
72

73
    /**
74
     * 点击节点的行为,`default` 为选中当前节点,`selectCheckbox` 为选中节点的 Checkbox, `thyCheckable` 为 true 时生效。
9✔
75
     * @default default
9✔
76
     */
5✔
77
    @Input() thyClickBehavior: ThyClickBehavior;
78

4✔
79
    /**
1✔
80
     * 设置节点名称是否支持超出截取
81
     * @default false
3!
82
     */
3!
83
    @Input({ transform: booleanAttribute }) thyTitleTruncate: boolean;
16✔
84

5✔
85
    /**
3✔
86
     * 设置 TreeNode 的渲染模板
87
     */
UNCOV
88
    @Input() templateRef: TemplateRef<any>;
×
89

90
    /**
91
     * 设置子的空数据渲染模板
9✔
92
     */
93
    @Input() emptyChildrenTemplateRef: TemplateRef<any>;
94

95
    /**
96
     * 设置 node 点击事件
97
     */
98
    @Output() thyOnClick: EventEmitter<ThyTreeEmitEvent> = new EventEmitter<ThyTreeEmitEvent>();
6✔
99

6✔
100
    /**
6!
101
     * 双击 node 事件
6✔
102
     */
103
    @Output() thyDblClick: EventEmitter<ThyTreeEmitEvent> = new EventEmitter<ThyTreeEmitEvent>();
104

105
    /**
106
     * 点击展开触发事件
6✔
107
     */
1✔
108
    @Output() thyOnExpandChange: EventEmitter<ThyTreeEmitEvent> = new EventEmitter<ThyTreeEmitEvent>();
109

110
    /**
111
     * 设置 check 选择事件
112
     */
1,034✔
113
    @Output() thyOnCheckboxChange: EventEmitter<ThyTreeEmitEvent> = new EventEmitter<ThyTreeEmitEvent>();
114

115
    /**
623✔
116
     * 设置 childrenTree 的渲染模板
117
     */
118
    @ContentChild('childrenTree') childrenTreeTemplateRef: TemplateRef<any>;
706✔
119

59✔
120
    /** The native `<div class="thy-tree-node-wrapper thy-sortable-item"></div>` element. */
121
    @ViewChild('treeNodeWrapper', { static: true }) treeNodeWrapper: ElementRef<HTMLElement>;
122

123
    @HostBinding('class.thy-tree-node') thyTreeNodeClass = true;
623✔
124

623✔
125
    @HostBinding('class') itemClass: string;
126

1✔
127
    /**
128
     * 开启虚拟滚动时,单行节点的高度,当`thySize`为`default`时,该参数才生效
129
     */
130
    @Input({ transform: numberAttribute }) thyItemSize = 44;
1✔
131

132
    /**
133
     * 设置节点缩进距离,缩进距离 = thyIndent * node.level
134
     */
135
    @Input({ transform: numberAttribute }) thyIndent = 25;
136

137
    public get nodeIcon() {
138
        return this.node.origin.icon;
139
    }
140

141
    public get nodeIconStyle() {
142
        return this.node.origin.iconStyle;
143
    }
144

145
    private destroy$ = new Subject<void>();
146

147
    checkState = ThyTreeNodeCheckState;
148

149
    constructor(@Inject(THY_TREE_ABSTRACT_TOKEN) public root: ThyTreeAbstractComponent, public thyTreeService: ThyTreeService) {}
150

151
    public clickNode(event: Event) {
152
        if (this.node.isDisabled) {
1✔
153
            this.expandNode(event);
154
        } else {
155
            if (this.thyCheckable && this.thyClickBehavior === 'selectCheckbox') {
156
                this.clickNodeCheck(event);
157
            } else {
158
                if (this.root.thyMultiple) {
159
                    this.root.toggleTreeNode(this.node);
160
                } else {
161
                    this.root.selectTreeNode(this.node);
162
                }
163
            }
164
        }
165
        this.thyOnClick.emit({
166
            eventName: 'click',
167
            event: event,
168
            node: this.node
169
        });
170
    }
171

172
    public dbClickNode(event: Event) {
173
        this.thyDblClick.emit({
174
            eventName: 'dbclick',
175
            event: event,
176
            node: this.node
177
        });
178
    }
179

180
    public clickNodeCheck(event: Event) {
181
        event.stopPropagation();
182
        if (this.node.isChecked === ThyTreeNodeCheckState.unchecked) {
183
            this.node.setChecked(true);
184
        } else if (this.node.isChecked === ThyTreeNodeCheckState.checked) {
185
            this.node.setChecked(false);
186
        } else if (this.node.isChecked === ThyTreeNodeCheckState.indeterminate) {
187
            if (this.node.children?.length) {
188
                const activeChildren = this.node.children.filter(item => !item.isDisabled);
189
                const isAllActiveChildrenChecked = activeChildren.every(item => item.isChecked);
190
                this.node.setChecked(!isAllActiveChildrenChecked);
191
            } else {
192
                this.node.setChecked(true);
193
            }
194
        }
195
        this.thyOnCheckboxChange.emit({
196
            eventName: 'checkboxChange',
197
            event: event,
198
            node: this.node
199
        });
200
    }
201

202
    public expandNode(event: Event) {
203
        event.stopPropagation();
204
        this.node.setExpanded(!this.node.isExpanded);
205
        if (this.root.thyShowExpand) {
206
            this.thyOnExpandChange.emit({
207
                eventName: 'expand',
208
                event: event,
209
                node: this.node
210
            });
211
            if (this.thyAsync && this.node.children.length === 0) {
212
                this.node.setLoading(true);
213
            }
214
        }
215
    }
216

217
    public isShowExpand(node: ThyTreeNode) {
218
        return this.root.isShowExpand(node);
219
    }
220

221
    ngOnInit(): void {
222
        this.itemClass = this.node?.itemClass?.join(' ');
223
    }
224

225
    ngOnChanges(changes: SimpleChanges): void {
226
        if (changes.node && !changes.node.isFirstChange()) {
227
            this.itemClass = changes?.node?.currentValue.itemClass?.join(' ');
228
        }
229
    }
230

231
    ngOnDestroy(): void {
232
        this.destroy$.next();
233
        this.destroy$.complete();
234
    }
235
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc