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

atinc / ngx-tethys / e62d3b10-1466-49c3-aabd-707148681fc8

14 Jun 2024 08:24AM UTC coverage: 90.422%. Remained the same
e62d3b10-1466-49c3-aabd-707148681fc8

push

circleci

minlovehua
feat: use the ngx-tethys/util's coerceBooleanProperty instead of booleanAttribute #INFR-12648

5467 of 6692 branches covered (81.69%)

Branch coverage included in aggregate %.

117 of 120 new or added lines in 66 files covered. (97.5%)

183 existing lines in 46 files now uncovered.

13216 of 13970 relevant lines covered (94.6%)

985.91 hits per line

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

92.86
/src/input/input-search.component.ts
1
import {
2
    AbstractControlValueAccessor,
3
    Constructor,
4
    mixinDisabled,
5
    mixinInitialized,
6
    mixinTabIndex,
7
    ThyCanDisable,
8
    ThyHasTabIndex,
9
    ThyInitialized,
10
    useHostFocusControl
11
} from 'ngx-tethys/core';
12

1✔
13
import { NgIf } from '@angular/common';
14
import {
16✔
15
    ChangeDetectionStrategy,
16
    ChangeDetectorRef,
17
    Component,
1✔
18
    ElementRef,
1✔
19
    EventEmitter,
20
    forwardRef,
21
    Input,
22
    OnDestroy,
23
    OnInit,
24
    Output,
1✔
25
    ViewChild,
26
    ViewEncapsulation
13✔
27
} from '@angular/core';
13✔
28
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
29
import { useHostRenderer } from '@tethys/cdk/dom';
30
import { ThyIcon } from 'ngx-tethys/icon';
13✔
31
import { ThyAutofocusDirective } from 'ngx-tethys/shared';
13✔
32
import { ThyInputDirective, ThyInputSize } from './input.directive';
33

34
import { FocusOrigin } from '@angular/cdk/a11y';
16✔
35
import { coerceBooleanProperty } from 'ngx-tethys/util';
16✔
36

16✔
37
export type ThyInputSearchTheme = 'default' | 'ellipse' | 'transparent' | '';
16✔
38
export type ThyInputSearchIconPosition = 'before' | 'after';
16✔
39

16✔
40
export const CUSTOM_INPUT_SEARCH_CONTROL_VALUE_ACCESSOR: any = {
16✔
41
    provide: NG_VALUE_ACCESSOR,
16✔
42
    useExisting: forwardRef(() => ThyInputSearch),
16✔
43
    multi: true
16✔
44
};
16✔
45

16✔
46
const noop = () => {};
16✔
47

48
const _MixinBase: Constructor<ThyHasTabIndex> &
49
    Constructor<ThyInitialized> &
16✔
50
    Constructor<ThyCanDisable> &
16✔
51
    typeof AbstractControlValueAccessor = mixinInitialized(mixinTabIndex(mixinDisabled(AbstractControlValueAccessor)));
16✔
52

10!
UNCOV
53
/**
×
54
 * 搜索输入框
55
 * @name thy-input-search
10✔
56
 * @order 30
8✔
57
 */
3✔
58
@Component({
59
    selector: 'thy-input-search',
60
    templateUrl: './input-search.component.html',
61
    providers: [CUSTOM_INPUT_SEARCH_CONTROL_VALUE_ACCESSOR],
2!
62
    encapsulation: ViewEncapsulation.None,
2✔
63
    changeDetection: ChangeDetectionStrategy.OnPush,
2✔
64
    host: {
65
        class: 'thy-input form-control thy-input-search',
66
        '[class.thy-input-search-ellipse]': 'thyTheme === "ellipse"',
10✔
67
        '[class.thy-input-search-transparent]': 'thyTheme === "transparent"',
68
        '[class.thy-input-search-before-with-clear]': 'searchText && iconPosition === "before"',
69
        '[class.form-control-active]': 'focused',
13✔
70
        '[attr.tabindex]': 'tabIndex'
29✔
71
    },
16✔
72
    standalone: true,
73
    imports: [NgIf, ThyIcon, ThyInputDirective, ThyAutofocusDirective, FormsModule]
74
})
75
export class ThyInputSearch extends _MixinBase implements ControlValueAccessor, OnInit, OnDestroy {
34✔
76
    @ViewChild('input', { static: true }) inputElement: ElementRef<any>;
34✔
77

78
    private hostRenderer = useHostRenderer();
79

17✔
80
    private hostFocusControl = useHostFocusControl();
81

82
    public disabled = false;
1✔
83

84
    public autoFocus = false;
85

2✔
86
    public iconPosition: ThyInputSearchIconPosition = 'before';
2✔
87

2✔
88
    searchText: string;
2!
UNCOV
89

×
90
    focused = false;
91

2✔
92
    /**
2✔
93
     * 搜索框 name 属性
2✔
94
     */
2✔
95
    @Input() name = '';
96

97
    /**
16✔
98
     * 搜索框 Placeholder
99
     */
1✔
100
    @Input() placeholder = '';
101

102
    /**
103
     * 搜索框风格
1✔
104
     * @type 'default' | 'ellipse' | 'transparent'
105
     * @default default
106
     */
107
    @Input() thyTheme: ThyInputSearchTheme;
108

109
    /**
110
     * 是否自动聚焦
111
     * @default false
112
     */
113
    @Input({ transform: coerceBooleanProperty })
114
    set thySearchFocus(value: boolean) {
115
        this.autoFocus = value;
1✔
116
        this.focused = value;
117
    }
118

119
    /**
120
     * 搜索图标位置,当传入 after 时,搜索图标在输入框后方显示,有内容时显示为关闭按钮
121
     * @type
122
     */
123
    @Input() set thyIconPosition(value: ThyInputSearchIconPosition) {
124
        this.iconPosition = value || 'before';
125
        this.updateClasses();
126
    }
127

128
    /**
129
     * 输入框大小
130
     * @type 'xs' | 'sm' | 'md' | 'default' | 'lg'
131
     */
132
    @Input() thySize: ThyInputSize;
133

134
    /**
135
     * @deprecated please use thyClear
136
     */
137
    @Output() clear: EventEmitter<Event> = new EventEmitter<Event>();
138

139
    /**
140
     * 清除搜索事件
141
     */
142
    @Output() thyClear: EventEmitter<Event> = new EventEmitter<Event>();
143

144
    constructor(private cdr: ChangeDetectorRef, private elementRef: ElementRef) {
145
        super();
146
    }
147

148
    ngOnInit(): void {
149
        super.ngOnInit();
150
        this.updateClasses(true);
151

152
        this.hostFocusControl.focusChanged = (origin: FocusOrigin) => {
153
            if (this.disabled) {
154
                return;
155
            }
156

157
            if (origin) {
158
                if (!this.focused) {
159
                    this.inputElement.nativeElement.focus();
160
                }
161
            } else {
162
                if (this.focused) {
163
                    this.focused = false;
164
                    this.onTouchedFn();
165
                }
166
            }
167
            this.cdr.markForCheck();
168
        };
169
    }
170

171
    updateClasses(forceUpdate = false) {
172
        if (this.initialized || forceUpdate) {
173
            this.hostRenderer.updateClass([`thy-input-search-${this.iconPosition}`]);
174
        }
175
    }
176

177
    writeValue(value: any): void {
178
        this.searchText = value;
179
        this.cdr.markForCheck();
180
    }
181

182
    setDisabledState?(isDisabled: boolean): void {
183
        this.disabled = isDisabled;
184
    }
185

186
    searchModelChange() {
187
        this.onChangeFn(this.searchText);
188
    }
189

190
    clearSearchText(event: Event) {
191
        const element = this.elementRef.nativeElement.querySelector('.input-search-control');
192
        element.focus();
193
        event.stopPropagation();
194
        if (this.disabled) {
195
            return;
196
        }
197
        this.searchText = '';
198
        this.onChangeFn(this.searchText);
199
        this.clear.emit(event);
200
        this.thyClear.emit(event);
201
    }
202

203
    ngOnDestroy(): void {
204
        this.hostFocusControl.destroy();
205
    }
206
}
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