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

IgniteUI / igniteui-angular / 12237137713

09 Dec 2024 01:55PM UTC coverage: 91.597% (-0.03%) from 91.622%
12237137713

Pull #15140

github

web-flow
Merge a88cb95a4 into 59a006fd6
Pull Request #15140: fix(*): icon service doesn't work with scoped themes

12983 of 15222 branches covered (85.29%)

45 of 53 new or added lines in 5 files covered. (84.91%)

13 existing lines in 2 files now uncovered.

26314 of 28728 relevant lines covered (91.6%)

34024.89 hits per line

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

83.87
/projects/igniteui-angular/src/lib/input-group/input-group.component.ts
1
import { DOCUMENT, NgIf, NgTemplateOutlet, NgClass, NgSwitch, NgSwitchCase, NgSwitchDefault } from '@angular/common';
2
import {
3
    AfterViewInit,
4
    ChangeDetectorRef,
5
    Component,
6
    ContentChild,
7
    ContentChildren,
8
    ElementRef,
9
    HostBinding,
10
    HostListener, Inject, Input,
11
    Optional, QueryList, booleanAttribute,
12
} from '@angular/core';
13
import { IInputResourceStrings, InputResourceStringsEN } from '../core/i18n/input-resources';
14
import { PlatformUtil, getComponentTheme } from '../core/utils';
15
import { IgxButtonDirective } from '../directives/button/button.directive';
16
import { IgxHintDirective } from '../directives/hint/hint.directive';
17
import {
18
    IgxInputDirective,
19
    IgxInputState
20
} from '../directives/input/input.directive';
21
import { IgxPrefixDirective } from '../directives/prefix/prefix.directive';
22
import { IgxSuffixDirective } from '../directives/suffix/suffix.directive';
23

24
import { IgxInputGroupBase } from './input-group.common';
25
import { IgxInputGroupType, IGX_INPUT_GROUP_TYPE } from './inputGroupType';
26
import { IgxIconComponent } from '../icon/icon.component';
27
import { getCurrentResourceStrings } from '../core/i18n/resources';
28
import { IgxTheme, THEME_TOKEN, ThemeToken } from '../services/theme/theme.token';
29

30
@Component({
31
    selector: 'igx-input-group',
32
    templateUrl: 'input-group.component.html',
33
    providers: [{ provide: IgxInputGroupBase, useExisting: IgxInputGroupComponent }],
34
    imports: [NgIf, NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent, NgSwitch, NgSwitchCase, NgSwitchDefault]
35
})
36
export class IgxInputGroupComponent implements IgxInputGroupBase, AfterViewInit {
2✔
37
    /**
38
     * Sets the resource strings.
39
     * By default it uses EN resources.
40
     */
41
    @Input()
42
    public set resourceStrings(value: IInputResourceStrings) {
UNCOV
43
        this._resourceStrings = Object.assign({}, this._resourceStrings, value);
×
44
    }
45

46
    /**
47
     * Returns the resource strings.
48
     */
49
    public get resourceStrings(): IInputResourceStrings {
50
        return this._resourceStrings;
35✔
51
    }
52

53
    /**
54
     * Property that enables/disables the auto-generated class of the `IgxInputGroupComponent`.
55
     * By default applied the class is applied.
56
     * ```typescript
57
     *  @ViewChild("MyInputGroup")
58
     *  public inputGroup: IgxInputGroupComponent;
59
     *  ngAfterViewInit(){
60
     *  this.inputGroup.defaultClass = false;
61
     * ```
62
     * }
63
     */
64
    @HostBinding('class.igx-input-group')
65
    public defaultClass = true;
2,492✔
66

67
    /** @hidden */
68
    @HostBinding('class.igx-input-group--placeholder')
69
    public hasPlaceholder = false;
2,492✔
70

71
    /** @hidden */
72
    @HostBinding('class.igx-input-group--required')
73
    public isRequired = false;
2,492✔
74

75
    /** @hidden */
76
    @HostBinding('class.igx-input-group--focused')
77
    public isFocused = false;
2,492✔
78

79
    /**
80
     * @hidden @internal
81
     * When truthy, disables the `IgxInputGroupComponent`.
82
     * Controlled by the underlying `IgxInputDirective`.
83
     * ```html
84
     * <igx-input-group [disabled]="true"></igx-input-group>
85
     * ```
86
     */
87
    @HostBinding('class.igx-input-group--disabled')
88
    public disabled = false;
2,492✔
89

90
    /**
91
     * Prevents automatically focusing the input when clicking on other elements in the input group (e.g. prefix or suffix).
92
     *
93
     * @remarks Automatic focus causes software keyboard to show on mobile devices.
94
     *
95
     * @example
96
     * ```html
97
     * <igx-input-group [suppressInputAutofocus]="true"></igx-input-group>
98
     * ```
99
     */
100
    @Input({ transform: booleanAttribute })
101
    public suppressInputAutofocus = false;
2,492✔
102

103
    /** @hidden */
104
    @HostBinding('class.igx-input-group--warning')
105
    public hasWarning = false;
2,492✔
106

107
    /** @hidden */
108
    @ContentChildren(IgxHintDirective, { read: IgxHintDirective })
109
    protected hints: QueryList<IgxHintDirective>;
110

111
    @ContentChildren(IgxPrefixDirective, { read: IgxPrefixDirective, descendants: true })
112
    protected _prefixes: QueryList<IgxPrefixDirective>;
113

114
    @ContentChildren(IgxSuffixDirective, { read: IgxSuffixDirective, descendants: true })
115
    protected _suffixes: QueryList<IgxSuffixDirective>;
116

117
    /** @hidden */
118
    @ContentChild(IgxInputDirective, { read: IgxInputDirective, static: true })
119
    protected input: IgxInputDirective;
120

121
    private _type: IgxInputGroupType = null;
2,492✔
122
    private _filled = false;
2,492✔
123
    private _theme: IgxTheme;
124
    private _resourceStrings = getCurrentResourceStrings(InputResourceStringsEN);
2,492✔
125

126
    /** @hidden */
127
    @HostBinding('class.igx-input-group--valid')
128
    public get validClass(): boolean {
129
        return this.input.valid === IgxInputState.VALID;
26,608✔
130
    }
131

132
    /** @hidden */
133
    @HostBinding('class.igx-input-group--invalid')
134
    public get invalidClass(): boolean {
135
        return this.input.valid === IgxInputState.INVALID;
26,608✔
136
    }
137

138
    /** @hidden */
139
    @HostBinding('class.igx-input-group--filled')
140
    public get isFilled() {
141
        return this._filled || (this.input && this.input.value);
26,678✔
142
    }
143

144
    /** @hidden */
145
    @HostBinding('class.igx-input-group--textarea-group')
146
    public get textAreaClass(): boolean {
147
        return this.input.isTextArea;
26,608✔
148
    }
149

150
    /**
151
     * Sets how the input will be styled.
152
     * Allowed values of type IgxInputGroupType.
153
     * ```html
154
     * <igx-input-group [type]="'search'">
155
     * ```
156
     */
157
    @Input()
158
    public set type(value: IgxInputGroupType) {
159
        this._type = value;
1,671✔
160
    }
161

162
    /**
163
     * Returns the type of the `IgxInputGroupComponent`. How the input is styled.
164
     * The default is `line`.
165
     * ```typescript
166
     * @ViewChild("MyInputGroup")
167
     * public inputGroup: IgxInputGroupComponent;
168
     * ngAfterViewInit(){
169
     *    let inputType = this.inputGroup.type;
170
     * }
171
     * ```
172
     */
173
    public get type() {
174
        return this._type || this._inputGroupType || 'line';
150,610✔
175
    }
176

177
    /**
178
     * Sets the theme of the input.
179
     * Allowed values of type IgxInputGroupTheme.
180
     * ```typescript
181
     * @ViewChild("MyInputGroup")
182
     * public inputGroup: IgxInputGroupComponent;
183
     * ngAfterViewInit() {
184
     *  let inputTheme = 'fluent';
185
     * }
186
     */
187
    @Input()
188
    public set theme(value: IgxTheme) {
UNCOV
189
        this._theme = value;
×
190
    }
191

192
    /**
193
     * Returns the theme of the input.
194
     * The returned value is of type IgxInputGroupType.
195
     * ```typescript
196
     * @ViewChild("MyInputGroup")
197
     * public inputGroup: IgxInputGroupComponent;
198
     * ngAfterViewInit() {
199
     *  let inputTheme = this.inputGroup.theme;
200
     * }
201
     */
202
    public get theme(): IgxTheme {
203
        return this._theme;
26,608✔
204
    }
205

206
    constructor(
207
        public element: ElementRef<HTMLElement>,
2,492✔
208
        @Optional()
209
        @Inject(IGX_INPUT_GROUP_TYPE)
210
        private _inputGroupType: IgxInputGroupType,
2,492✔
211
        @Inject(DOCUMENT)
212
        private document: any,
2,492✔
213
        private platform: PlatformUtil,
2,492✔
214
        private cdr: ChangeDetectorRef,
2,492✔
215
        @Inject(THEME_TOKEN)
216
        private themeToken: ThemeToken
2,492✔
217
    ) {
218
        this._theme = this.themeToken.theme;
2,492✔
219

220
        this.themeToken.onChange((theme) => {
2,492✔
221
            if (this._theme !== theme) {
2,492!
NEW
UNCOV
222
                this._theme = theme;
×
NEW
223
                this.cdr.detectChanges();
×
224
            }
225
        });
226
    }
227

228
    /** @hidden */
229
    @HostListener('click', ['$event'])
230
    public onClick(event: MouseEvent) {
231
        if (
150✔
232
            !this.isFocused &&
303✔
233
            event.target !== this.input.nativeElement &&
234
            !this.suppressInputAutofocus
235
        ) {
236
            this.input.focus();
66✔
237
        }
238
    }
239

240
    /** @hidden */
241
    @HostListener('pointerdown', ['$event'])
242
    public onPointerDown(event: PointerEvent) {
243
        if (this.isFocused && event.target !== this.input.nativeElement) {
11✔
244
            event.preventDefault();
3✔
245
        }
246
    }
247

248
    /** @hidden @internal */
249
    public hintClickHandler(event: MouseEvent) {
250
        event.stopPropagation();
2✔
251
    }
252

253
    /**
254
     * Returns whether the `IgxInputGroupComponent` has hints.
255
     * ```typescript
256
     * @ViewChild("MyInputGroup")
257
     * public inputGroup: IgxInputGroupComponent;
258
     * ngAfterViewInit(){
259
     *    let inputHints = this.inputGroup.hasHints;
260
     * }
261
     * ```
262
     */
263
    public get hasHints() {
UNCOV
264
        return this.hints.length > 0;
×
265
    }
266

267
    /** @hidden @internal */
268
    @HostBinding('class.igx-input-group--prefixed')
269
    public get hasPrefixes() {
270
        return this._prefixes.length > 0 || this.isFileType;
26,608✔
271
    }
272

273
    /** @hidden @internal */
274
    public set prefixes(items: QueryList<IgxPrefixDirective>) {
275
        this._prefixes = items;
448✔
276
    }
277

278
    /** @hidden @internal */
279
    @HostBinding('class.igx-input-group--suffixed')
280
    public get hasSuffixes() {
281
        return this._suffixes.length > 0 || this.isFileType && this.isFilled;
26,608✔
282
    }
283

284
    /** @hidden @internal */
285
    public set suffixes(items: QueryList<IgxPrefixDirective>) {
286
        this._suffixes = items;
35✔
287
    }
288

289
    /**
290
     * Returns whether the `IgxInputGroupComponent` has border.
291
     * ```typescript
292
     * @ViewChild("MyInputGroup")
293
     * public inputGroup: IgxInputGroupComponent;
294
     * ngAfterViewInit(){
295
     *    let inputBorder = this.inputGroup.hasBorder;
296
     * }
297
     * ```
298
     */
299
    public get hasBorder() {
300
        return (
26,608✔
301
            (this.type === 'line' || this.type === 'box') &&
67,946✔
302
            this._theme === 'material'
303
        );
304
    }
305

306
    /**
307
     * Returns whether the `IgxInputGroupComponent` type is line.
308
     * ```typescript
309
     * @ViewChild("MyInputGroup1")
310
     * public inputGroup: IgxInputGroupComponent;
311
     * ngAfterViewInit(){
312
     *    let isTypeLine = this.inputGroup.isTypeLine;
313
     * }
314
     * ```
315
     */
316
    public get isTypeLine(): boolean {
317
        return this.type === 'line' && this._theme === 'material';
45✔
318
    }
319

320
    /**
321
     * Returns whether the `IgxInputGroupComponent` type is box.
322
     * ```typescript
323
     * @ViewChild("MyInputGroup1")
324
     * public inputGroup: IgxInputGroupComponent;
325
     * ngAfterViewInit(){
326
     *    let isTypeBox = this.inputGroup.isTypeBox;
327
     * }
328
     * ```
329
     */
330
    @HostBinding('class.igx-input-group--box')
331
    public get isTypeBox() {
332
        return this.type === 'box' && this._theme === 'material';
53,226✔
333
    }
334

335
    /** @hidden @internal */
336
    public uploadButtonHandler() {
UNCOV
337
        this.input.nativeElement.click();
×
338
    }
339

340
    /** @hidden @internal */
341
    public clearValueHandler() {
342
        this.input.clear();
2✔
343
    }
344

345
    /** @hidden @internal */
346
    @HostBinding('class.igx-input-group--file')
347
    public get isFileType() {
348
        return this.input.type === 'file';
129,954✔
349
    }
350

351
    /** @hidden @internal */
352
    public get fileNames() {
353
        return this.input.fileNames || this._resourceStrings.igx_input_file_placeholder;
70✔
354
    }
355

356
    /**
357
     * Returns whether the `IgxInputGroupComponent` type is border.
358
     * ```typescript
359
     * @ViewChild("MyInputGroup1")
360
     * public inputGroup: IgxInputGroupComponent;
361
     * ngAfterViewInit(){
362
     *    let isTypeBorder = this.inputGroup.isTypeBorder;
363
     * }
364
     * ```
365
     */
366
    @HostBinding('class.igx-input-group--border')
367
    public get isTypeBorder() {
368
        return this.type === 'border' && this._theme === 'material';
26,618✔
369
    }
370

371
    /**
372
     * Returns true if the `IgxInputGroupComponent` theme is Fluent.
373
     * ```typescript
374
     * @ViewChild("MyInputGroup1")
375
     * public inputGroup: IgxInputGroupComponent;
376
     * ngAfterViewInit(){
377
     *    let isTypeFluent = this.inputGroup.isTypeFluent;
378
     * }
379
     * ```
380
     */
381
    @HostBinding('class.igx-input-group--fluent')
382
    public get isTypeFluent() {
383
        return this._theme === 'fluent';
26,608✔
384
    }
385

386
    /**
387
     * Returns true if the `IgxInputGroupComponent` theme is Bootstrap.
388
     * ```typescript
389
     * @ViewChild("MyInputGroup1")
390
     * public inputGroup: IgxInputGroupComponent;
391
     * ngAfterViewInit(){
392
     *    let isTypeBootstrap = this.inputGroup.isTypeBootstrap;
393
     * }
394
     * ```
395
     */
396
    @HostBinding('class.igx-input-group--bootstrap')
397
    public get isTypeBootstrap() {
398
        return this._theme === 'bootstrap';
26,608✔
399
    }
400

401
    /**
402
     * Returns true if the `IgxInputGroupComponent` theme is Indigo.
403
     * ```typescript
404
     * @ViewChild("MyInputGroup1")
405
     * public inputGroup: IgxInputGroupComponent;
406
     * ngAfterViewInit(){
407
     *    let isTypeIndigo = this.inputGroup.isTypeIndigo;
408
     * }
409
     * ```
410
     */
411
    @HostBinding('class.igx-input-group--indigo')
412
    public get isTypeIndigo() {
413
        return this._theme === 'indigo';
26,608✔
414
    }
415

416
    /**
417
     * Returns whether the `IgxInputGroupComponent` type is search.
418
     * ```typescript
419
     * @ViewChild("MyInputGroup1")
420
     * public inputGroup: IgxInputGroupComponent;
421
     * ngAfterViewInit(){
422
     *    let isTypeSearch = this.inputGroup.isTypeSearch;
423
     * }
424
     * ```
425
     */
426
    @HostBinding('class.igx-input-group--search')
427
    public get isTypeSearch() {
428
        return this.type === 'search';
26,618✔
429
    }
430

431
    /** @hidden */
432
    public get filled() {
UNCOV
433
        return this._filled;
×
434
    }
435

436
    /** @hidden */
437
    public set filled(val) {
438
        this._filled = val;
×
439
    }
440

441
    private setComponentTheme() {
442
        if (!this.themeToken.preferToken) {
2,492✔
443
            const theme = getComponentTheme(this.element.nativeElement);
2,492✔
444

445
            if (theme && theme !== this._theme) {
2,492!
NEW
446
                this.themeToken.set(theme);
×
NEW
447
                this.cdr.markForCheck();
×
448
            }
449
        }
450
    }
451

452
    /** @hidden @internal */
453
    public ngAfterViewInit() {
454
        this.setComponentTheme();
2,492✔
455
    }
456
}
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

© 2026 Coveralls, Inc