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

atinc / ngx-tethys / d9ae709b-3c27-4b69-b125-b8b80b54f90b

pending completion
d9ae709b-3c27-4b69-b125-b8b80b54f90b

Pull #2757

circleci

mengshuicmq
fix: fix code review
Pull Request #2757: feat(color-picker): color-picker support disabled (#INFR-8645)

98 of 6315 branches covered (1.55%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

2392 of 13661 relevant lines covered (17.51%)

83.12 hits per line

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

5.32
/src/shared/select/select-control/select-control.component.ts
1
import { InputBoolean, InputNumber } from 'ngx-tethys/core';
2
import { ThyTagSize } from 'ngx-tethys/tag';
3
import { isUndefinedOrNull } from 'ngx-tethys/util';
4

5
import {
6
    ChangeDetectionStrategy,
7
    Component,
8
    ElementRef,
9
    EventEmitter,
10
    Input,
11
    OnInit,
12
    Output,
13
    Renderer2,
14
    TemplateRef,
1✔
15
    ViewChild
16
} from '@angular/core';
×
17
import { useHostRenderer } from '@tethys/cdk/dom';
18

19
import { NgClass, NgFor, NgIf, NgStyle, NgTemplateOutlet } from '@angular/common';
×
20
import { FormsModule } from '@angular/forms';
×
21
import { ThyIconComponent } from 'ngx-tethys/icon';
×
22
import { ThyTagComponent } from 'ngx-tethys/tag';
×
23
import { SelectOptionBase } from '../../option/select-option-base';
24

25
export type SelectControlSize = 'sm' | 'md' | 'lg' | '';
×
26

×
27
/**
×
28
 * @private
29
 */
30
@Component({
×
31
    selector: 'thy-select-control,[thySelectControl]',
32
    templateUrl: './select-control.component.html',
33
    changeDetection: ChangeDetectionStrategy.OnPush,
×
34
    standalone: true,
35
    imports: [FormsModule, NgClass, NgIf, NgStyle, NgFor, ThyTagComponent, NgTemplateOutlet, ThyIconComponent]
36
})
×
37
export class ThySelectControlComponent implements OnInit {
×
38
    inputValue = '';
39

40
    isComposing = false;
×
41

42
    panelOpened = false;
43

×
44
    isMultiple = false;
×
45

46
    showSearch = false;
47

×
48
    disabled = false;
49

50
    size: SelectControlSize;
×
51

×
52
    selectedOptions: SelectOptionBase | SelectOptionBase[];
×
53

×
54
    searchInputControlClass: { [key: string]: boolean };
×
55

56
    tagSize: ThyTagSize;
57

58
    private hostRenderer = useHostRenderer();
×
59

×
60
    @Input()
61
    @InputBoolean()
62
    get thyPanelOpened(): boolean {
×
63
        return this.panelOpened;
×
64
    }
×
65

×
66
    set thyPanelOpened(value: boolean) {
×
67
        this.panelOpened = value;
68
        if (this.panelOpened && this.thyShowSearch) {
69
            Promise.resolve(null).then(() => {
70
                this.inputElement.nativeElement.focus();
×
71
            });
×
72
        }
73
        if (!this.panelOpened && this.thyShowSearch) {
74
            Promise.resolve(null).then(() => {
75
                this.setInputValue('');
76
            });
×
77
        }
78
        this.setSelectControlClass();
79
    }
×
80

×
81
    @Input()
82
    @InputBoolean()
83
    get thyIsMultiple(): boolean {
×
84
        return this.isMultiple;
85
    }
86

×
87
    set thyIsMultiple(value: boolean) {
×
88
        this.isMultiple = value;
×
89
        this.setSelectControlClass();
×
90
    }
91

×
92
    @Input()
×
93
    @InputBoolean()
94
    get thyShowSearch(): boolean {
95
        return this.showSearch;
×
96
    }
97

98
    set thyShowSearch(value: boolean) {
99
        this.showSearch = value;
×
100
        this.setSelectControlClass();
×
101
    }
×
102

×
103
    @Input()
104
    get thySelectedOptions(): SelectOptionBase | SelectOptionBase[] {
105
        return this.selectedOptions;
×
106
    }
107

108
    set thySelectedOptions(value: SelectOptionBase | SelectOptionBase[]) {
109
        let sameValue = false;
×
110
        const oldValue = this.selectedOptions;
111
        if (this.isMultiple) {
×
112
            if (oldValue instanceof Array && value instanceof Array && oldValue.length === value.length) {
113
                sameValue = value.every((option, index) => option.thyValue === oldValue[index].thyValue);
114
            }
×
115
        } else {
×
116
            if (oldValue && value) {
×
117
                sameValue = (oldValue as SelectOptionBase).thyValue === (value as SelectOptionBase).thyValue;
118
            }
×
119
        }
×
120
        this.selectedOptions = value;
121
        if (this.panelOpened && this.thyShowSearch) {
×
122
            if (!sameValue) {
×
123
                Promise.resolve(null).then(() => {
124
                    this.setInputValue('');
×
125
                });
126
            }
127
            //等待组件渲染好再聚焦
×
128
            setTimeout(() => {
129
                this.inputElement.nativeElement.focus();
130
            }, 200);
×
131
        }
132
    }
133

×
134
    @Input()
×
135
    @InputBoolean()
136
    get thyDisabled(): boolean {
×
137
        return this.disabled;
138
    }
139

×
140
    set thyDisabled(value: boolean) {
141
        this.disabled = value;
142
        this.setSelectControlClass();
×
143
    }
144

145
    @Input()
146
    customDisplayTemplate: TemplateRef<any>;
×
147

×
148
    @Input()
×
149
    @InputBoolean()
×
150
    thyAllowClear = false;
×
151

×
152
    @Input()
×
153
    thyPlaceholder = '';
×
154

×
155
    @Input()
×
156
    get thySize(): SelectControlSize {
×
157
        return this.size;
×
158
    }
×
159

×
160
    set thySize(value: SelectControlSize) {
×
161
        this.size = value;
162
        this.setSelectControlClass();
163

×
164
        if (value === 'sm') {
165
            this.tagSize = 'sm';
166
        } else if (value === 'lg') {
×
167
            this.tagSize = 'lg';
×
168
        } else {
169
            this.tagSize = 'md';
170
        }
171
    }
172

173
    @Input() @InputNumber() thyMaxTagCount = 0;
174

175
    @Output()
176
    thyOnSearch = new EventEmitter<string>();
177

×
178
    @Output()
×
179
    public thyOnRemove = new EventEmitter<{ item: SelectOptionBase; $eventOrigin: Event }>();
180

181
    @Output()
182
    public thyOnClear = new EventEmitter<Event>();
183

184
    @Output()
185
    public thyOnBlur = new EventEmitter<Event>();
186

×
187
    @ViewChild('inputElement')
×
188
    inputElement: ElementRef;
×
189

×
190
    get selectedValueStyle(): { [key: string]: string } {
191
        let showSelectedValue = false;
192
        if (this.showSearch) {
193
            if (this.panelOpened) {
×
194
                showSelectedValue = !(this.isComposing || this.inputValue);
×
195
            } else {
196
                showSelectedValue = true;
×
197
            }
×
198
        } else {
×
199
            showSelectedValue = true;
200
        }
201
        return { display: showSelectedValue ? 'block' : 'none' };
202
    }
203

×
204
    get placeholderStyle(): { [key: string]: string } {
×
205
        let placeholder = true;
×
206
        if (this.isSelectedValue) {
207
            placeholder = false;
208
        }
×
209
        if (!this.thyPlaceholder) {
210
            placeholder = false;
211
        }
212
        if (this.isComposing || this.inputValue) {
213
            placeholder = false;
×
214
        }
215
        return { display: placeholder ? 'block' : 'none' };
216
    }
×
217

218
    get selectedValue(): any {
219
        return this.thySelectedOptions;
×
220
    }
221

222
    get multipleSelectedValue(): any {
×
223
        return this.thySelectedOptions;
224
    }
1✔
225

226
    get maxSelectedTags() {
227
        if (this.thyMaxTagCount > 0 && this.thySelectedOptions instanceof Array && this.thySelectedOptions.length > this.thyMaxTagCount) {
1✔
228
            return this.thySelectedOptions.slice(0, this.thyMaxTagCount - 1);
229
        }
230
        return this.thySelectedOptions as SelectOptionBase[];
231
    }
232

233
    get showClearIcon(): boolean {
234
        return this.thyAllowClear && this.isSelectedValue;
235
    }
236

237
    get isSelectedValue(): boolean {
238
        return (
239
            (!this.isMultiple && !isUndefinedOrNull(this.thySelectedOptions)) ||
240
            (this.isMultiple && (<SelectOptionBase[]>this.thySelectedOptions).length > 0)
241
        );
242
    }
243

244
    constructor(private renderer: Renderer2) {}
245

1✔
246
    ngOnInit() {
247
        this.setSelectControlClass();
248
    }
249

250
    setSelectControlClass() {
1✔
251
        const modeType = this.isMultiple ? 'multiple' : 'single';
252
        const selectControlClass = {
253
            [`form-control`]: true,
254
            [`form-control-${this.thySize}`]: !!this.thySize,
255
            [`form-control-custom`]: true,
1✔
256
            [`select-control`]: true,
257
            [`select-control-${modeType}`]: true,
258
            [`select-control-show-search`]: this.showSearch,
259
            [`panel-is-opened`]: this.panelOpened,
260
            [`disabled`]: this.disabled
1✔
261
        };
262
        this.hostRenderer.updateClassByMap(selectControlClass);
263
        this.searchInputControlClass = {
264
            [`form-control`]: true,
265
            [`form-control-${this.thySize}`]: !!this.thySize,
1✔
266
            [`search-input-field`]: true,
267
            [`hidden`]: !this.thyShowSearch
268
        };
269
    }
1✔
270

271
    setInputValue(value: string) {
272
        if (value !== this.inputValue) {
273
            this.inputValue = value;
1✔
274
            this.updateWidth();
275
            this.thyOnSearch.emit(this.inputValue);
276
        }
277
    }
278

279
    handleBackspace(event: Event) {
280
        if ((event as KeyboardEvent).isComposing) {
281
            return;
282
        }
283
        if (this.inputValue.length === 0 && this.selectedOptions instanceof Array) {
284
            if (this.selectedOptions.length > 0) {
285
                this.removeHandle(this.selectedOptions[this.selectedOptions.length - 1], event);
286
            }
287
        }
288
    }
289

290
    updateWidth() {
291
        if (this.isMultiple && this.thyShowSearch) {
292
            if (this.inputValue || this.isComposing) {
293
                this.renderer.setStyle(this.inputElement.nativeElement, 'width', `${this.inputElement.nativeElement.scrollWidth}px`);
294
            } else {
295
                this.renderer.removeStyle(this.inputElement.nativeElement, 'width');
296
            }
297
        }
298
    }
299

300
    removeHandle(item: SelectOptionBase, $event: Event) {
301
        this.thyOnRemove.emit({ item: item, $eventOrigin: $event });
302
    }
303

304
    clearHandle($event: Event) {
305
        this.thyOnClear.emit($event);
306
    }
307

308
    trackValue(_index: number, option: SelectOptionBase): any {
309
        return option.thyValue;
310
    }
311

312
    onBlur(event: Event) {
313
        this.thyOnBlur.emit(event);
314
    }
315
}
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