-
-
Notifications
You must be signed in to change notification settings - Fork 835
Expand file tree
/
Copy pathtext-input-cmp.tsx
More file actions
88 lines (77 loc) · 2.72 KB
/
text-input-cmp.tsx
File metadata and controls
88 lines (77 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { Component, h, ReactiveControllerHost, State, Element } from '@stencil/core';
import { ValidationController } from './validation-controller.js';
import { FocusController } from './focus-controller.js';
@Component({
tag: 'composition-text-input',
})
export class TextInputCmp extends ReactiveControllerHost {
@Element() el!: HTMLElement;
@State() value: string = '';
@State() helperText: string = 'Enter your name';
// Controllers via composition
private validation = new ValidationController(this);
private focusController = new FocusController(this);
private inputId = `text-input-${Math.random().toString(36).substr(2, 9)}`;
private helperTextId = `${this.inputId}-helper-text`;
private errorTextId = `${this.inputId}-error-text`;
componentWillLoad() {
super.componentWillLoad(); // Call base class to trigger controllers
// Set up validation callback
this.validation.setValidationCallback((val: string) => {
if (!val || val.trim().length === 0) {
return 'Name is required';
}
if (val.length < 2) {
return 'Name must be at least 2 characters';
}
return undefined;
});
}
componentDidLoad() {
super.componentDidLoad(); // Call base class to trigger controllers
}
disconnectedCallback() {
super.disconnectedCallback(); // Call base class to trigger controllers
}
private handleInput = (e: Event) => {
const input = e.target as HTMLInputElement;
this.value = input.value;
};
private handleFocus = () => {
this.focusController.handleFocus();
};
private handleBlur = () => {
this.focusController.handleBlur();
this.validation.handleBlur(this.value);
};
render() {
const focusState = this.focusController.getFocusState();
const validationState = this.validation.getValidationState();
const validationData = this.validation.getValidationMessageData(this.helperTextId, this.errorTextId);
return (
<div class="text-input-container">
<label htmlFor={this.inputId}>Name</label>
<input
id={this.inputId}
type="text"
value={this.value}
onInput={this.handleInput}
onFocus={this.handleFocus}
onBlur={this.handleBlur}
class={validationState.isValid ? '' : 'invalid'}
/>
{validationData.hasError && (
<div class="validation-message">
<div id={validationData.errorTextId} class="error-text">
{validationData.errorMessage}
</div>
</div>
)}
<div class="focus-info">
Focused: {focusState.isFocused ? 'Yes' : 'No'} | Focus Count: {focusState.focusCount} | Blur Count:{' '}
{focusState.blurCount}
</div>
</div>
);
}
}