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

atinc / ngx-tethys / c23d9340-38e3-4237-9415-e2322c46bb87

16 May 2025 05:36AM UTC coverage: 90.283% (+0.009%) from 90.274%
c23d9340-38e3-4237-9415-e2322c46bb87

Pull #3419

circleci

invalid-email-address
fix: add readonly for computed
Pull Request #3419: refactor(input): migrate to signal for input #TINFR-1478

5618 of 6889 branches covered (81.55%)

Branch coverage included in aggregate %.

36 of 38 new or added lines in 5 files covered. (94.74%)

7 existing lines in 3 files now uncovered.

13447 of 14228 relevant lines covered (94.51%)

917.67 hits per line

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

94.34
/src/input/input.component.ts
1
import { take } from 'rxjs/operators';
2

3
import { NgTemplateOutlet } from '@angular/common';
4
import {
5
    Component,
6
    ElementRef,
7
    forwardRef,
8
    NgZone,
9
    OnInit,
10
    TemplateRef,
11
    ViewEncapsulation,
12
    inject,
1✔
13
    input,
14
    effect,
28✔
15
    signal,
16
    output,
17
    contentChild
1✔
18
} from '@angular/core';
1✔
19
import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
20
import { ThyIcon } from 'ngx-tethys/icon';
21
import { ThyAutofocusDirective } from 'ngx-tethys/shared';
22
import { ThyInputDirective, ThyInputSize } from './input.directive';
23
import { coerceBooleanProperty } from 'ngx-tethys/util';
24

1✔
25
export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
26
    provide: NG_VALUE_ACCESSOR,
42✔
27
    useExisting: forwardRef(() => ThyInput),
42✔
28
    multi: true
42✔
29
};
42✔
30

42✔
31
const noop = () => {};
42✔
32

42✔
33
const password = 'password';
42✔
34

42✔
35
/**
42✔
36
 * 内部集成输入框组件,建议 thy-input-group 和 thyInput 组合使用
42✔
37
 * @name thy-input
42✔
38
 * @order 50
42✔
39
 */
42✔
40
@Component({
42✔
41
    selector: 'thy-input',
42✔
42
    templateUrl: './input.component.html',
42✔
43
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR],
42✔
44
    encapsulation: ViewEncapsulation.None,
42✔
45
    host: {
42✔
46
        class: 'thy-input form-control',
43✔
47
        '[class.form-control-active]': 'focused',
48
        '[class.disabled]': 'disabled'
49
    },
50
    imports: [NgTemplateOutlet, ThyInputDirective, ThyAutofocusDirective, FormsModule, ThyIcon]
42✔
51
})
42✔
52
export class ThyInput implements ControlValueAccessor, OnInit {
53
    private ngZone = inject(NgZone);
54
    private elementRef = inject(ElementRef);
55

56✔
56
    /**
57
     * Placeholder
58
     */
28✔
59
    readonly placeholder = input('');
60

61
    /**
28✔
62
     * 输入框大小
63
     * @type 'xs' | 'sm' | 'md' | 'default' | 'lg'
64
     * @default default
29✔
65
     */
66
    readonly thySize = input<ThyInputSize>();
UNCOV
67

×
68
    /**
69
     * 是否自动聚焦
70
     */
3✔
71
    readonly thyAutofocus = input(false, { transform: coerceBooleanProperty });
3✔
72

3✔
73
    /**
74
     * 输入框类型
75
     * @type 'number' | 'input'
1✔
76
     */
1!
NEW
77
    readonly thyType = input<string>();
×
78

79
    /**
1✔
80
     * @deprecated please use thyType
1✔
81
     */
1✔
82
    readonly _type = input<string>(undefined, { alias: 'type' });
83

84
    /**
68✔
85
     * 输入 Label 文本
86
     */
87
    readonly thyLabelText = input<string>(undefined);
2✔
88

89
    /**
1✔
90
     * 是否只读
1✔
91
     */
92
    readonly readonly = input(false, { transform: coerceBooleanProperty });
93

94
    /**
95
     * focus 聚焦事件
96
     */
97
    readonly focus = output<Event>();
98

99
    /**
100
     * blur 失焦事件
101
     */
102
    readonly blur = output<Event>();
103

104
    /**
1✔
105
     * 后置模板
106
     */
107
    readonly appendTemplate = contentChild<TemplateRef<any>>('append');
108

109
    /**
110
     * 前置模板
111
     */
112
    readonly prependTemplate = contentChild<TemplateRef<any>>('prepend');
113

114
    public type = signal<string>(undefined);
115

116
    public value: string;
117

118
    public showLabel: boolean;
119

120
    public focused = false;
121

122
    public disabled = false;
123

124
    private onTouchedCallback: () => void = noop;
125

126
    private onChangeCallback: (_: any) => void = noop;
127

128
    public isPasswordType = signal(false);
129

130
    constructor() {
131
        effect(() => {
132
            this.type.set(this.thyType() || this._type());
133
        });
134
    }
135

136
    ngOnInit() {
137
        this.ngZone.onStable.pipe(take(1)).subscribe(() => {
138
            this.isPasswordType.set(this.isPassword(this.type()));
139
        });
140
    }
141

142
    writeValue(value: any): void {
143
        this.value = value;
144
    }
145

146
    registerOnChange(fn: any): void {
147
        this.onChangeCallback = fn;
148
    }
149

150
    registerOnTouched(fn: any): void {
151
        this.onTouchedCallback = fn;
152
    }
153

154
    setDisabledState?(isDisabled: boolean): void {
155
        this.disabled = isDisabled;
156
    }
157

158
    onModelChange() {
159
        this.onChangeCallback(this.value);
160
    }
161

162
    onInputFocus(event: Event) {
163
        this.focused = true;
164
        this.showLabel = true;
165
        this.focus.emit(event);
166
    }
167

168
    onInputBlur(event: Event) {
169
        this.onTouchedCallback();
170
        if (this.elementRef.nativeElement.onblur) {
171
            this.elementRef.nativeElement.onblur(event);
172
        }
173
        this.focused = false;
174
        this.showLabel = false;
175
        this.blur.emit(event);
176
    }
177

178
    isPassword(value: string) {
179
        return value === password;
180
    }
181

182
    togglePasswordType() {
183
        this.type.set(this.isPassword(this.type()) ? 'text' : 'password');
184
    }
185
}
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