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

atinc / ngx-tethys / 9e7524c1-cc0e-404f-af8a-1d90ccdbe28d

24 Nov 2023 05:42AM UTC coverage: 90.289% (-0.001%) from 90.29%
9e7524c1-cc0e-404f-af8a-1d90ccdbe28d

Pull #2917

circleci

minlovehua
feat(switch): support thyLoading and loading animation INFR-10495
Pull Request #2917: feat(switch): support thyLoading and loading animation INFR-10495

5316 of 6547 branches covered (0.0%)

Branch coverage included in aggregate %.

16 of 17 new or added lines in 1 file covered. (94.12%)

2 existing lines in 2 files now uncovered.

13233 of 13997 relevant lines covered (94.54%)

976.75 hits per line

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

93.75
/src/switch/switch.component.ts
1
import { coerceBooleanProperty } from 'ngx-tethys/util';
2

3
import { NgClass, NgIf } from '@angular/common';
4
import {
5
    ChangeDetectionStrategy,
6
    ChangeDetectorRef,
7
    Component,
8
    ElementRef,
9
    EventEmitter,
10
    forwardRef,
11
    Input,
12
    OnInit,
13
    Output,
14
    ViewChild
1✔
15
} from '@angular/core';
16
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
8✔
17
import { InputBoolean, TabIndexDisabledControlValueAccessorMixin } from 'ngx-tethys/core';
4✔
18

19
/**
8✔
20
 * 开关组件
8✔
21
 * @name thy-switch
3✔
22
 * @order 10
23
 */
24
@Component({
25
    selector: 'thy-switch',
6!
26
    templateUrl: './switch.component.html',
×
27
    changeDetection: ChangeDetectionStrategy.OnPush,
28
    providers: [
6✔
29
        {
6✔
30
            provide: NG_VALUE_ACCESSOR,
1✔
31
            useExisting: forwardRef(() => ThySwitchComponent),
32
            multi: true
6!
UNCOV
33
        }
×
34
    ],
35
    standalone: true,
36
    imports: [NgClass, NgIf],
37
    host: {
706✔
38
        class: 'thy-switch',
39
        '[class.thy-switch-xs]': 'size === "xs"',
40
        '[class.thy-switch-sm]': 'size === "sm"'
7✔
41
    }
7✔
42
})
43
export class ThySwitchComponent extends TabIndexDisabledControlValueAccessorMixin implements OnInit, ControlValueAccessor {
44
    public model: boolean;
6✔
45

6✔
46
    public type?: string = 'primary';
1✔
47

48
    public size?: string = '';
6✔
49

1✔
50
    public disabled?: boolean = false;
1✔
51

52
    public loading: boolean = false;
53

54
    public classNames: string[];
327✔
55

327✔
56
    public typeArray: string[] = ['primary', 'info', 'warning', 'danger'];
327✔
57

327✔
58
    public sizeArray: string[] = ['', 'sm', 'xs'];
327✔
59

327✔
60
    public loadingCircle: {
327✔
61
        viewBox?: string;
327✔
62
        cx?: number;
327✔
63
        cy?: number;
327✔
64
        r?: number;
327✔
65
        dasharray?: string;
327✔
66
    } = {};
327✔
67

327✔
68
    private initialized = false;
327✔
69

70
    private loadingInitialized = false;
71

323✔
72
    private isDisabledFirstChange = true;
323✔
73

74
    @ViewChild('switch', { static: true }) switchElementRef: ElementRef;
75

646✔
76
    /**
646✔
77
     * 类型,目前分为: 'primary' |'info' | 'warning' | 'danger'
78
     */
79
    @Input()
80
    set thyType(value: string) {
323✔
81
        if (!this.typeArray.includes(value)) {
82
            value = 'primary';
83
        }
323✔
84
        this.type = value;
85
        if (this.initialized) {
86
            this.setClassNames();
328✔
87
        }
328✔
88
    }
328✔
89

90
    /**
91
     * 大小
1✔
92
     * @type xs | sm | md
1✔
93
     * @default md
1✔
94
     */
1✔
95
    @Input()
96
    set thySize(value: string) {
97
        if (!this.sizeArray.includes(value)) {
663✔
98
            value = '';
663✔
99
        }
4✔
100
        this.size = value;
101
        if (this.initialized) {
663✔
102
            this.setClassNames();
8✔
103
        }
8!
NEW
104

×
105
        if (this.loadingInitialized) {
106
            this.setLoadingCircle();
107
        }
663✔
108
    }
109

110
    /**
1✔
111
     * 是否属于禁用状态
112
     */
113
    @Input()
114
    override get thyDisabled(): boolean {
115
        return this.disabled;
1✔
116
    }
1✔
117

1✔
118
    override set thyDisabled(value: boolean) {
1✔
119
        this.disabled = coerceBooleanProperty(value);
120
        this.setClassNames();
121
    }
122

123
    /**
124
     * 是否加载中
125
     */
1✔
126
    @Input() @InputBoolean() set thyLoading(value: boolean) {
127
        this.loading = value;
1✔
128
        if (this.initialized) {
129
            this.setClassNames();
130
        }
1✔
131

132
        if (this.loading && !this.loadingInitialized) {
133
            this.setLoadingCircle();
134
            this.loadingInitialized = true;
135
        }
136
    }
137

138
    /**
139
     * 数据变化的回调事件,即将被弃用,请使用 ngModelChange
1✔
140
     * @deprecated
141
     */
142
    @Output() thyChange: EventEmitter<Event> = new EventEmitter<Event>();
143

144
    constructor(public cdr: ChangeDetectorRef) {
1✔
145
        super();
146
    }
147

148
    ngOnInit() {
149
        this.setClassNames();
150
        this.initialized = true;
151
    }
152

327✔
153
    public onModelChange: Function = () => {};
154

155
    public onModelTouched: Function = () => {};
156

157
    writeValue(value: boolean) {
158
        this.model = value;
159
        this.cdr.markForCheck();
160
        // this.setClassNames();
161
    }
162

163
    registerOnChange(fn: Function): void {
164
        this.onModelChange = fn;
165
    }
166

167
    registerOnTouched(fn: Function): void {
168
        this.onModelTouched = fn;
169
    }
170

171
    setDisabledState(isDisabled: boolean): void {
172
        this.disabled = (this.isDisabledFirstChange && this.thyDisabled) || isDisabled;
173
        this.isDisabledFirstChange = false;
174
        this.setClassNames();
175
    }
176

177
    toggle(event: Event) {
178
        this.model = !this.model;
179
        this.onModelChange(this.model);
180
        this.onModelTouched();
181
        this.thyChange.emit(event);
182
    }
183

184
    setClassNames() {
185
        this.classNames = [`thy-switch-${this.type}`];
186
        if (this.size) {
187
            this.classNames.push(`thy-switch-${this.size}`);
188
        }
189
        if (this.disabled || this.loading) {
190
            this.classNames.push(`thy-switch-disabled`);
191
            if (this.model) {
192
                this.classNames.push(`thy-switch-disabled-true`);
193
            }
194
        }
195
        this.cdr.markForCheck();
196
    }
197

198
    setLoadingCircle() {
199
        const svgSize = {
200
            ['xs']: 12,
201
            ['sm']: 16,
202
            ['']: 20
203
        };
204

205
        const circleSize = svgSize[this.size];
206
        const centerPoint = circleSize / 2;
207
        const r = circleSize / 4;
208

209
        this.loadingCircle = {
210
            viewBox: `0 0 ${circleSize} ${circleSize}`,
211
            cx: centerPoint,
212
            cy: centerPoint,
213
            r: r,
214
            dasharray: `${2 * Math.PI * r * 0.75} ${2 * Math.PI * r * 0.25}`
215
        };
216
        this.cdr.markForCheck();
217
    }
218
}
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