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

atinc / ngx-tethys / ebc321d8-d8ed-4ed1-9e59-a5945729a8da

24 Aug 2023 02:49AM UTC coverage: 90.055% (-0.1%) from 90.181%
ebc321d8-d8ed-4ed1-9e59-a5945729a8da

Pull #2771

circleci

web-flow
feat(dropdown): update thyImmediateRender template remove div #INFR-9359 (#2794)

* feat(dropdown): update thyImmediateRender template remove div #INFR-9359

* feat(dropdown): update test

* feat(dropdown): update test

* build: code review

* build: code review
Pull Request #2771: feat: bump angular to 16.x

5104 of 6321 branches covered (80.75%)

Branch coverage included in aggregate %.

144 of 144 new or added lines in 15 files covered. (100.0%)

12897 of 13668 relevant lines covered (94.36%)

977.88 hits per line

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

94.32
/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,
14
    OnDestroy,
1✔
15
    OnInit,
16
    Output,
17
    SimpleChanges,
18
    TemplateRef,
19
    ViewChild,
20
    ViewEncapsulation
1✔
21
} from '@angular/core';
22

237✔
23
import { THY_TREE_ABSTRACT_TOKEN, ThyTreeAbstractComponent } from './tree-abstract';
24
import { ThyTreeNode } from './tree-node.class';
25
import { ThyTreeEmitEvent, ThyTreeNodeCheckState, ThyClickBehavior } from './tree.class';
×
26
import { ThyTreeService } from './tree.service';
27
import { InputBoolean, InputNumber } from 'ngx-tethys/core';
28
import { ThyLoadingComponent } from 'ngx-tethys/loading';
632✔
29
import { ThyIconComponent } from 'ngx-tethys/icon';
632✔
30
import { NgIf, NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
632✔
31

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

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

52
    /**
53
     * 设置 TreeNode 是否支持异步加载
3✔
54
     */
1✔
55
    @Input() @InputBoolean() thyAsync = false;
56

57
    /**
2✔
58
     * 设置 TreeNode 是否支持多选节点
59
     */
60
    @Input() @InputBoolean() thyMultiple = false;
61

7✔
62
    /**
63
     * 设置 TreeNode 是否支持拖拽排序
64
     */
65
    @Input() @InputBoolean() thyDraggable = false;
66

67
    /**
68
     * 设置 TreeNode 是否支持 Checkbox 选择
1✔
69
     */
70
    @Input() @InputBoolean() thyCheckable = false;
71

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

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

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

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

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

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

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

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

1,072✔
114
    /**
115
     * 设置 childrenTree 的渲染模板
116
     */
632✔
117
    @ContentChild('childrenTree') childrenTreeTemplateRef: TemplateRef<any>;
118

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

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

124
    @HostBinding('class') itemClass: string;
632✔
125

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

131
    /**
1✔
132
     * 设置节点缩进距离,缩进距离 = thyIndent * node.level
133
     */
134
    @Input() @InputNumber() thyIndent = 25;
135

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

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

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

146
    checkState = ThyTreeNodeCheckState;
147

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

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

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

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

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

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

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

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

230
    ngOnDestroy(): void {
231
        this.destroy$.next();
232
        this.destroy$.complete();
233
    }
234
}
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