Skip to content

Commit 402520b

Browse files
authored
Use custom events for inputs (#42)
* In-progress: use custom events for inputs * Pass events to parent component * Add unit test for plan-details * Add E2E test * Replace Listener with callback * Make E2E props more readable * PR feedback
1 parent 1833266 commit 402520b

File tree

15 files changed

+501
-177
lines changed

15 files changed

+501
-177
lines changed

src/components.d.ts

Lines changed: 11 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,11 @@ import {
1919
} from './types/Input';
2020
import {
2121
Option,
22-
Value,
2322
} from 'types/Select';
2423

2524

2625
export namespace Components {
2726

28-
interface CustomPlanFeature {
29-
'feature': Catalog.ExpandedFeature;
30-
'planLabel': string;
31-
'selectedValue': string;
32-
}
33-
interface CustomPlanFeatureAttributes extends StencilHTMLAttributes {
34-
'feature'?: Catalog.ExpandedFeature;
35-
'planLabel'?: string;
36-
'selectedValue'?: string;
37-
}
38-
3927
interface FeaturedService {
4028
'logo': string;
4129
'name': string;
@@ -193,61 +181,62 @@ export namespace Components {
193181
}
194182

195183
interface MfSelect {
184+
'defaultValue'?: string;
196185
'name': string;
197-
'onChange': (e: UIEvent) => void;
198186
'options': Option[];
199187
'required'?: boolean;
200-
'selectedValue'?: Value;
201188
}
202189
interface MfSelectAttributes extends StencilHTMLAttributes {
190+
'defaultValue'?: string;
203191
'name'?: string;
204-
'onChange'?: (e: UIEvent) => void;
192+
'onUpdateValue'?: (event: CustomEvent) => void;
205193
'options'?: Option[];
206194
'required'?: boolean;
207-
'selectedValue'?: Value;
208195
}
209196

210197
interface MfSlider {
198+
'defaultValue'?: number;
211199
'error'?: string;
212200
'increment': number;
213201
'max': number;
214202
'min': number;
215203
'name': string;
216-
'onChange': (e: Event) => void;
217-
'selectedValue': number;
218204
'suffix': string;
219205
}
220206
interface MfSliderAttributes extends StencilHTMLAttributes {
207+
'defaultValue'?: number;
221208
'error'?: string;
222209
'increment'?: number;
223210
'max'?: number;
224211
'min'?: number;
225212
'name'?: string;
226-
'onChange'?: (e: Event) => void;
227-
'selectedValue'?: number;
213+
'onUpdateValue'?: (event: CustomEvent) => void;
228214
'suffix'?: string;
229215
}
230216

231217
interface MfToggle {
232218
'ariaLabelledby'?: string;
219+
'defaultValue'?: boolean;
233220
'disabled'?: boolean;
234221
'label'?: string;
235222
'name': string;
236223
}
237224
interface MfToggleAttributes extends StencilHTMLAttributes {
238225
'ariaLabelledby'?: string;
226+
'defaultValue'?: boolean;
239227
'disabled'?: boolean;
240228
'label'?: string;
241229
'name'?: string;
230+
'onUpdateValue'?: (event: CustomEvent) => void;
242231
}
243232

244233
interface PlanDetails {
245234
'plan': Catalog.ExpandedPlan;
246-
'product': Catalog.ExpandedProduct;
235+
'product': Catalog.Product;
247236
}
248237
interface PlanDetailsAttributes extends StencilHTMLAttributes {
249238
'plan'?: Catalog.ExpandedPlan;
250-
'product'?: Catalog.ExpandedProduct;
239+
'product'?: Catalog.Product;
251240
}
252241

253242
interface PlanMenu {
@@ -332,7 +321,6 @@ export namespace Components {
332321

333322
declare global {
334323
interface StencilElementInterfaces {
335-
'CustomPlanFeature': Components.CustomPlanFeature;
336324
'FeaturedService': Components.FeaturedService;
337325
'ImageGallery': Components.ImageGallery;
338326
'LinkButton': Components.LinkButton;
@@ -360,7 +348,6 @@ declare global {
360348
}
361349

362350
interface StencilIntrinsicElements {
363-
'custom-plan-feature': Components.CustomPlanFeatureAttributes;
364351
'featured-service': Components.FeaturedServiceAttributes;
365352
'image-gallery': Components.ImageGalleryAttributes;
366353
'link-button': Components.LinkButtonAttributes;
@@ -388,12 +375,6 @@ declare global {
388375
}
389376

390377

391-
interface HTMLCustomPlanFeatureElement extends Components.CustomPlanFeature, HTMLStencilElement {}
392-
var HTMLCustomPlanFeatureElement: {
393-
prototype: HTMLCustomPlanFeatureElement;
394-
new (): HTMLCustomPlanFeatureElement;
395-
};
396-
397378
interface HTMLFeaturedServiceElement extends Components.FeaturedService, HTMLStencilElement {}
398379
var HTMLFeaturedServiceElement: {
399380
prototype: HTMLFeaturedServiceElement;
@@ -539,7 +520,6 @@ declare global {
539520
};
540521

541522
interface HTMLElementTagNameMap {
542-
'custom-plan-feature': HTMLCustomPlanFeatureElement
543523
'featured-service': HTMLFeaturedServiceElement
544524
'image-gallery': HTMLImageGalleryElement
545525
'link-button': HTMLLinkButtonElement
@@ -567,7 +547,6 @@ declare global {
567547
}
568548

569549
interface ElementTagNameMap {
570-
'custom-plan-feature': HTMLCustomPlanFeatureElement;
571550
'featured-service': HTMLFeaturedServiceElement;
572551
'image-gallery': HTMLImageGalleryElement;
573552
'link-button': HTMLLinkButtonElement;

src/components/custom-plan-feature/custom-plan-feature.tsx

Lines changed: 0 additions & 73 deletions
This file was deleted.

src/components/custom-plan-feature/readme.md

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/components/mf-select/mf-select.tsx

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,32 @@
1-
import { Component, Prop } from '@stencil/core';
2-
import { Option, Value } from 'types/Select';
1+
import { Component, Prop, Event, EventEmitter, Watch } from '@stencil/core';
2+
import { Option } from 'types/Select';
33

44
@Component({
55
tag: 'mf-select',
66
styleUrl: 'mf-select.css',
77
scoped: true,
88
})
99
export class MfSelect {
10-
@Prop() options: Option[] = [];
11-
@Prop() selectedValue?: Value;
10+
@Prop() defaultValue?: string;
1211
@Prop() name: string;
12+
@Prop() options: Option[] = [];
1313
@Prop() required?: boolean;
14-
@Prop() onChange: (e: UIEvent) => void;
14+
@Event() updateValue: EventEmitter;
15+
@Watch('defaultValue') watchHandler(newVal: string) {
16+
this.updateValue.emit({ name: this.name, value: newVal });
17+
}
18+
19+
onChangeHandler = (e: Event) => {
20+
if (!e.target) return;
21+
const { value } = e.target as HTMLSelectElement;
22+
this.updateValue.emit({ name: this.name, value });
23+
};
1524

1625
render() {
1726
return (
18-
<select name={this.name} required={this.required} onChange={this.onChange}>
27+
<select name={this.name} required={this.required} onChange={this.onChangeHandler}>
1928
{this.options.map(({ label, value }) => (
20-
<option value={value} selected={this.selectedValue === value}>
29+
<option value={value} selected={value === this.defaultValue}>
2130
{label}
2231
</option>
2332
))}

src/components/mf-select/readme.md

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,19 @@
77

88
## Properties
99

10-
| Property | Attribute | Description | Type | Default |
11-
| --------------- | ---------------- | ----------- | ------------------------------- | ----------- |
12-
| `name` | `name` | | `string` | `undefined` |
13-
| `onChange` | -- | | `(e: UIEvent) => void` | `undefined` |
14-
| `options` | -- | | `Option[]` | `[]` |
15-
| `required` | `required` | | `boolean \| undefined` | `undefined` |
16-
| `selectedValue` | `selected-value` | | `number \| string \| undefined` | `undefined` |
10+
| Property | Attribute | Description | Type | Default |
11+
| -------------- | --------------- | ----------- | ---------------------- | ----------- |
12+
| `defaultValue` | `default-value` | | `string \| undefined` | `undefined` |
13+
| `name` | `name` | | `string` | `undefined` |
14+
| `options` | -- | | `Option[]` | `[]` |
15+
| `required` | `required` | | `boolean \| undefined` | `undefined` |
16+
17+
18+
## Events
19+
20+
| Event | Description | Type |
21+
| ------------- | ----------- | ------------------- |
22+
| `updateValue` | | `CustomEvent<void>` |
1723

1824

1925
----------------------------------------------

src/components/mf-slider/mf-slider.tsx

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, Prop } from '@stencil/core';
1+
import { Component, Prop, Event, EventEmitter, Watch } from '@stencil/core';
22
import { FieldType } from '../../types/Input';
33

44
@Component({
@@ -7,21 +7,33 @@ import { FieldType } from '../../types/Input';
77
scoped: true,
88
})
99
export class MfSlider {
10-
@Prop() min: number = 0;
11-
@Prop() max: number;
10+
@Prop() defaultValue?: number;
11+
@Prop() error?: string;
1212
@Prop() increment: number = 1;
13+
@Prop() max: number;
14+
@Prop() min: number = 0;
1315
@Prop() name: string = '';
14-
@Prop() selectedValue: number;
1516
@Prop() suffix: string = '';
16-
@Prop() onChange: (e: Event) => void;
17-
@Prop() error?: string;
17+
@Event() updateValue: EventEmitter;
18+
@Watch('defaultValue') watchHandler(newVal: number) {
19+
this.updateValue.emit({ name: this.name, value: newVal });
20+
}
21+
22+
onChangeHandler = (e: Event) => {
23+
if (!e.target) return;
24+
const { value } = e.target as HTMLInputElement;
25+
this.updateValue.emit({
26+
name: this.name,
27+
value: parseInt(value, 10),
28+
});
29+
};
1830

1931
get positionCount() {
2032
return (this.max - this.min) / this.increment;
2133
}
2234

2335
render() {
24-
const value = this.selectedValue || this.min;
36+
const value = this.defaultValue || this.min;
2537
return (
2638
<div class="container">
2739
{this.positionCount < 500 ? (
@@ -32,8 +44,6 @@ export class MfSlider {
3244
min={this.min}
3345
step={this.increment}
3446
value={value}
35-
onInput={e => this.onChange(e)}
36-
onChange={e => this.onChange(e)}
3747
style={{
3848
'--slider-position': `${value / (this.max - this.min)}%`,
3949
}}
@@ -53,10 +63,10 @@ export class MfSlider {
5363
type={FieldType.Number}
5464
max={this.max}
5565
min={this.min}
56-
value={value}
57-
onChange={e => this.onChange(e)}
66+
onChange={this.onChangeHandler}
5867
required
5968
step={this.increment}
69+
value={value}
6070
/>
6171
<div class="display-units">{this.suffix}</div>
6272
</div>

0 commit comments

Comments
 (0)