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

IgniteUI / igniteui-webcomponents / 21029997016

15 Jan 2026 11:39AM UTC coverage: 98.199% (-0.04%) from 98.242%
21029997016

Pull #2058

github

web-flow
Merge 67221e2ae into d2c366a75
Pull Request #2058: Refactor input-based inheritance chain for several components

5302 of 5586 branches covered (94.92%)

Branch coverage included in aggregate %.

336 of 344 new or added lines in 7 files covered. (97.67%)

1 existing line in 1 file now uncovered.

35699 of 36167 relevant lines covered (98.71%)

1604.87 hits per line

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

96.92
/src/components/input/input.ts
1
import { html } from 'lit';
22✔
2
import { property } from 'lit/decorators.js';
22✔
3
import { ifDefined } from 'lit/directives/if-defined.js';
22✔
4
import { live } from 'lit/directives/live.js';
22✔
5
import { addThemingController } from '../../theming/theming-controller.js';
22✔
6
import { addSlotController, setSlots } from '../common/controllers/slot.js';
22✔
7
import { registerComponent } from '../common/definitions/register.js';
22✔
8
import { createFormValueState } from '../common/mixins/forms/form-value.js';
22✔
9
import { partMap } from '../common/part-map.js';
22✔
10
import { bindIf } from '../common/util.js';
22✔
11
import type {
22✔
12
  InputType,
22✔
13
  RangeTextSelectMode,
22✔
14
  SelectionRangeDirection,
22✔
15
} from '../types.js';
22✔
16
import IgcValidationContainerComponent from '../validation-container/validation-container.js';
22✔
17
import { IgcInputBaseComponent } from './input-base.js';
22✔
18
import { styles } from './themes/input.base.css.js';
22✔
19
import { styles as shared } from './themes/shared/input.common.css.js';
22✔
20
import { all } from './themes/themes.js';
22✔
21
import { numberValidators, stringValidators } from './validators.js';
22✔
22

22✔
23
const Slots = setSlots(
22✔
24
  'prefix',
22✔
25
  'suffix',
22✔
26
  'helper-text',
22✔
27
  'value-missing',
22✔
28
  'type-mismatch',
22✔
29
  'pattern-mismatch',
22✔
30
  'too-long',
22✔
31
  'too-short',
22✔
32
  'range-overflow',
22✔
33
  'range-underflow',
22✔
34
  'step-mismatch',
22✔
35
  'custom-error',
22✔
36
  'invalid'
22✔
37
);
22✔
38

22✔
39
/**
22✔
40
 * @element igc-input
22✔
41
 *
22✔
42
 * @slot prefix - Renders content before the input.
22✔
43
 * @slot suffix - Renders content after input.
22✔
44
 * @slot helper-text - Renders content below the input.
22✔
45
 * @slot value-missing - Renders content when the required validation fails.
22✔
46
 * @slot type-mismatch - Renders content when the a type url/email input pattern validation fails.
22✔
47
 * @slot pattern-mismatch - Renders content when the pattern validation fails.
22✔
48
 * @slot too-long - Renders content when the maxlength validation fails.
22✔
49
 * @slot too-short - Renders content when the minlength validation fails.
22✔
50
 * @slot range-overflow - Renders content when the max validation fails.
22✔
51
 * @slot range-underflow - Renders content when the min validation fails.
22✔
52
 * @slot step-mismatch - Renders content when the step validation fails.
22✔
53
 * @slot custom-error - Renders content when setCustomValidity(message) is set.
22✔
54
 * @slot invalid - Renders content when the component is in invalid state (validity.valid = false).
22✔
55
 *
22✔
56
 * @fires igcInput - Emitted when the control input receives user input.
22✔
57
 * @fires igcChange - Emitted when the control's checked state changes.
22✔
58
 *
22✔
59
 * @csspart container - The main wrapper that holds all main input elements.
22✔
60
 * @csspart input - The native input element.
22✔
61
 * @csspart label - The native label element.
22✔
62
 * @csspart prefix - The prefix wrapper.
22✔
63
 * @csspart suffix - The suffix wrapper.
22✔
64
 * @csspart helper-text - The helper text wrapper.
22✔
65
 */
22✔
66
export default class IgcInputComponent extends IgcInputBaseComponent {
519✔
67
  public static readonly tagName = 'igc-input';
519✔
68
  public static styles = [styles, shared];
519✔
69

519✔
70
  /* blazorSuppress */
519✔
71
  public static register(): void {
519✔
72
    registerComponent(IgcInputComponent, IgcValidationContainerComponent);
12✔
73
  }
12✔
74

519✔
75
  protected override readonly _themes = addThemingController(this, all);
519✔
76

519✔
77
  protected override readonly _slots = addSlotController(this, {
519✔
78
    slots: Slots,
519✔
79
  });
519✔
80

519✔
81
  protected override readonly _formValue = createFormValueState(this, {
519✔
82
    initialValue: '',
519✔
83
  });
519✔
84

519✔
85
  protected override get __validators() {
519✔
86
    return this.type !== 'number' ? stringValidators : numberValidators;
1,531✔
87
  }
1,531✔
88

519✔
89
  private _min?: number;
519✔
90
  private _max?: number;
519✔
91
  private _minLength?: number;
519✔
92
  private _maxLength?: number;
519✔
93
  private _pattern?: string;
519✔
94
  private _step?: number;
519✔
95

519✔
96
  /* @tsTwoWayProperty(true, "igcChange", "detail", false) */
519✔
97
  /**
519✔
98
   * The value of the control.
519✔
99
   * @attr
519✔
100
   */
519✔
101
  @property()
519✔
102
  public set value(value: string) {
519✔
103
    this._formValue.setValueAndFormState(value);
657✔
104
  }
657✔
105

519✔
106
  public get value(): string {
519✔
107
    return this._formValue.value;
11,768✔
108
  }
11,768✔
109

519✔
110
  /* alternateName: displayType */
519✔
111
  /**
519✔
112
   * The type attribute of the control.
519✔
113
   * @attr
519✔
114
   */
519✔
115
  @property({ reflect: true })
519✔
116
  public type: InputType = 'text';
519✔
117

519✔
118
  /**
519✔
119
   * Makes the control a readonly field.
519✔
120
   *
519✔
121
   * @attr readonly
519✔
122
   * @default false
519✔
123
   */
519✔
124
  @property({ type: Boolean, reflect: true })
519✔
125
  public readOnly = false;
519✔
126

519✔
127
  /**
519✔
128
   * The input mode attribute of the control.
519✔
129
   * See [relevant MDN article](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/inputmode)
519✔
130
   * @attr inputmode
519✔
131
   */
519✔
132
  @property({ attribute: 'inputmode' })
519✔
133
  public override inputMode!: string;
519✔
134

519✔
135
  /**
519✔
136
   * The pattern attribute of the control.
519✔
137
   * @attr
519✔
138
   */
519✔
139
  @property()
519✔
140
  public set pattern(value: string | undefined) {
519✔
141
    this._pattern = value;
6✔
142
    this._validate();
6✔
143
  }
6✔
144

519✔
145
  public get pattern(): string | undefined {
519✔
146
    return this._pattern;
3,228✔
147
  }
3,228✔
148

519✔
149
  /**
519✔
150
   * The minimum string length required by the control.
519✔
151
   * @attr minlength
519✔
152
   */
519✔
153
  @property({ type: Number, attribute: 'minlength' })
519✔
154
  public set minLength(value: number | undefined) {
519✔
155
    this._minLength = value;
7✔
156
    this._validate();
7✔
157
  }
7✔
158

519✔
159
  public get minLength(): number | undefined {
519✔
160
    return this._minLength;
3,237✔
161
  }
3,237✔
162

519✔
163
  /**
519✔
164
   * The maximum string length of the control.
519✔
165
   * @attr maxlength
519✔
166
   */
519✔
167
  @property({ type: Number, attribute: 'maxlength' })
519✔
168
  public set maxLength(value: number | undefined) {
519✔
169
    this._maxLength = value;
6✔
170
    this._validate();
6✔
171
  }
6✔
172

519✔
173
  public get maxLength(): number | undefined {
519✔
174
    return this._maxLength;
3,232✔
175
  }
3,232✔
176

519✔
177
  /**
519✔
178
   * The min attribute of the control.
519✔
179
   * @attr
519✔
180
   */
519✔
181
  @property({ type: Number })
519✔
182
  public set min(value: number | undefined) {
519✔
183
    this._min = value;
6✔
184
    this._validate();
6✔
185
  }
6✔
186

519✔
187
  public get min(): number | undefined {
519✔
188
    return this._min;
1,866✔
189
  }
1,866✔
190

519✔
191
  /**
519✔
192
   * The max attribute of the control.
519✔
193
   * @attr
519✔
194
   */
519✔
195
  @property({ type: Number })
519✔
196
  public set max(value: number | undefined) {
519✔
197
    this._max = value;
6✔
198
    this._validate();
6✔
199
  }
6✔
200

519✔
201
  public get max(): number | undefined {
519✔
202
    return this._max;
1,812✔
203
  }
1,812✔
204

519✔
205
  /**
519✔
206
   * The step attribute of the control.
519✔
207
   * @attr
519✔
208
   */
519✔
209
  @property({ type: Number })
519✔
210
  public set step(value: number | undefined) {
519✔
211
    this._step = value;
7✔
212
    this._validate();
7✔
213
  }
7✔
214

519✔
215
  public get step(): number | undefined {
519✔
216
    return this._step;
1,806✔
217
  }
1,806✔
218

519✔
219
  /**
519✔
220
   * The autofocus attribute of the control.
519✔
221
   * @attr
519✔
222
   */
519✔
223
  @property({ type: Boolean })
519✔
224
  public override autofocus!: boolean;
519✔
225

519✔
226
  /**
519✔
227
   * The autocomplete attribute of the control.
519✔
228
   * @attr
519✔
229
   */
519✔
230
  @property()
519✔
231
  public autocomplete!: string;
519✔
232

519✔
233
  /**
519✔
234
   * Enables validation rules to be evaluated without restricting user input. This applies to the `maxLength` property for
519✔
235
   * string-type inputs or allows spin buttons to exceed the predefined `min/max` limits for number-type inputs.
519✔
236
   *
519✔
237
   * @attr validate-only
519✔
238
   * @default false
519✔
239
   */
519✔
240
  @property({ type: Boolean, reflect: true, attribute: 'validate-only' })
519✔
241
  public validateOnly = false;
519✔
242

22✔
243
  /* blazorSuppress */
22✔
244
  /** Replaces the selected text in the input. */
22✔
245
  public setRangeText(
22✔
246
    replacement: string,
1✔
247
    start?: number,
1✔
248
    end?: number,
1✔
249
    selectMode: RangeTextSelectMode = 'preserve'
1✔
250
  ): void {
1✔
251
    this._input?.setRangeText(replacement, start!, end!, selectMode);
1✔
252
    this.value = this._input?.value ?? '';
1!
253
  }
1✔
254

22✔
255
  /* blazorSuppress */
22✔
256
  /** Sets the text selection range of the control */
22✔
257
  public setSelectionRange(
22✔
NEW
258
    start?: number,
×
NEW
259
    end?: number,
×
NEW
260
    direction: SelectionRangeDirection = 'none'
×
NEW
261
  ): void {
×
NEW
262
    this._input?.setSelectionRange(start ?? null, end ?? null, direction);
×
UNCOV
263
  }
×
264

22✔
265
  /** Increments the numeric value of the input by one or more steps. */
22✔
266
  public stepUp(n?: number): void {
22✔
267
    this._input?.stepUp(n);
2✔
268
    this.value = this._input?.value ?? '';
2!
269
  }
2✔
270

22✔
271
  /** Decrements the numeric value of the input by one or more steps. */
22✔
272
  public stepDown(n?: number): void {
22✔
273
    this._input?.stepDown(n);
2✔
274
    this.value = this._input?.value ?? '';
2!
275
  }
2✔
276

22✔
277
  private _handleInput(): void {
22✔
278
    this._setTouchedState();
6✔
279
    this.value = this._input?.value ?? '';
6!
280
    this.emitEvent('igcInput', { detail: this.value });
6✔
281
  }
6✔
282

22✔
283
  private _handleChange(): void {
22✔
284
    this._setTouchedState();
1✔
285
    this.value = this._input?.value ?? '';
1!
286
    this.emitEvent('igcChange', { detail: this.value });
1✔
287
  }
1✔
288

22✔
289
  protected _renderInput() {
22✔
290
    const hasNegativeTabIndex = this.getAttribute('tabindex') === '-1';
1,232✔
291
    const hasHelperText = this._slots.hasAssignedElements('helper-text');
1,232✔
292

1,232✔
293
    return html`
1,232✔
294
      <input
1,232✔
295
        id=${this._inputId}
1,232✔
296
        part=${partMap(this._resolvePartNames('input'))}
1,232✔
297
        name=${ifDefined(this.name)}
1,232✔
298
        type=${ifDefined(this.type)}
1,232✔
299
        pattern=${ifDefined(this.pattern)}
1,232✔
300
        placeholder=${ifDefined(this.placeholder)}
1,232✔
301
        .value=${live(this.value)}
1,232✔
302
        ?readonly=${this.readOnly}
1,232✔
303
        ?disabled=${this.disabled}
1,232✔
304
        ?required=${this.required}
1,232✔
305
        ?autofocus=${this.autofocus}
1,232✔
306
        tabindex=${bindIf(hasNegativeTabIndex, -1)}
1,232✔
307
        autocomplete=${ifDefined(this.autocomplete as any)}
1,232✔
308
        inputmode=${ifDefined(this.inputMode)}
1,232✔
309
        min=${bindIf(!this.validateOnly, this.min)}
1,232✔
310
        max=${bindIf(!this.validateOnly, this.max)}
1,232✔
311
        minlength=${ifDefined(this.minLength)}
1,232✔
312
        maxlength=${bindIf(!this.validateOnly, this.maxLength)}
1,232✔
313
        step=${ifDefined(this.step)}
1,232✔
314
        aria-describedby=${bindIf(hasHelperText, 'helper-text')}
1,232✔
315
        @change=${this._handleChange}
1,232✔
316
        @input=${this._handleInput}
1,232✔
317
        @blur=${this._handleBlur}
1,232✔
318
      />
1,232✔
319
    `;
1,232✔
320
  }
1,232✔
321
}
22✔
322

22✔
323
declare global {
22✔
324
  interface HTMLElementTagNameMap {
22✔
325
    'igc-input': IgcInputComponent;
22✔
326
  }
22✔
327
}
22✔
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