Skip to content

Commit 33374c1

Browse files
committed
Updates for elements
1 parent 9e2ab25 commit 33374c1

File tree

9 files changed

+363
-209
lines changed

9 files changed

+363
-209
lines changed

src/component/button/ButtonElement.js

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,24 @@ import Event from '../../core/Event';
66
* A button element
77
*/
88
export class ButtonElement extends LitElement {
9+
#internals;
10+
911
constructor() {
1012
super();
13+
14+
// Attach with the form
15+
this.#internals = this.attachInternals();
16+
1117
// Default properties
1218
this.name = '';
1319
this.disabled = false;
1420
this.link = '';
1521
this.transform = 'none';
1622
this.submit = false;
23+
this.default = false;
24+
}
25+
static get formAssociated() {
26+
return true;
1727
}
1828
static get properties() {
1929
return {
@@ -43,9 +53,15 @@ export class ButtonElement extends LitElement {
4353

4454
/**
4555
* The text transform, none, uppercase, lowercase,capitalize
46-
* @type {String}
56+
* @type {Boolean}
4757
*/
4858
submit: { type: Boolean },
59+
60+
/**
61+
* Whether the button is the default button
62+
* @type {Boolean}
63+
*/
64+
default: { type: Boolean },
4965
};
5066
}
5167

@@ -91,6 +107,9 @@ export class ButtonElement extends LitElement {
91107
background-color: var(--button-background-color-disabled);
92108
font-weight: var(--button-font-weight-disabled);
93109
}
110+
.default {
111+
font-weight: var(--button-font-weight-default);
112+
}
94113
.text-transform-capitalize {
95114
text-transform: capitalize;
96115
}
@@ -112,25 +131,49 @@ export class ButtonElement extends LitElement {
112131
return html`
113132
${this.link
114133
? html`
115-
<a role="button" class="button ${this.transform ? `text-transform-${this.transform}` : ''}" href="${this.link}" ?disabled="${this.disabled}" @click=${this.onClick}>
134+
<a role="button" class="button ${this.transform ? `text-transform-${this.transform}` : ''} ${this.default ? 'default' : ''}" href="${this.link}" ?disabled="${this.disabled}" @click=${this.onClick}>
116135
<slot></slot>
117136
</a>
118137
`
119138
: html`
120-
<button role="button" type="${this.buttonType()}" class="button ${this.transform ? `text-transform-${this.transform}` : ''}" ?disabled="${this.disabled}" @click=${this.onClick}>
139+
<button role="button" type="${this.buttonType()}" class="button ${this.transform ? `text-transform-${this.transform}` : ''} ${this.default ? 'default' : ''}" ?disabled="${this.disabled}" @click=${this.onClick}>
121140
<slot></slot>
122141
</button>
123142
`}
124143
`;
125144
}
126-
onClick() {
145+
onClick(evt) {
146+
// If the button is in a form, then create a temporary button to submit the form
147+
const form = this.formElement();
148+
if (form && this.submit) {
149+
evt.preventDefault();
150+
const tmpButton = document.createElement("button");
151+
tmpButton.type = "submit";
152+
tmpButton.name = this.name;
153+
tmpButton.value = this.textContent;
154+
tmpButton.style.display = "none";
155+
form.appendChild(tmpButton);
156+
tmpButton.click();
157+
158+
let formData = new FormData(form, tmpButton);
159+
let formValues = {};
160+
for (let [key, value] of formData.entries()) {
161+
formValues[key] = value;
162+
}
163+
tmpButton.remove();
164+
console.log(formValues);
165+
}
166+
167+
// Dispatch a click event
127168
this.dispatchEvent(new CustomEvent(
128169
Event.EVENT_CLICK, {
129170
bubbles: true,
130171
composed: true,
131172
detail: this.name || this.textContent
132-
},
133-
));
173+
}));
174+
}
175+
formElement() {
176+
return this.#internals.form;
134177
}
135178
}
136179

src/component/form/FormElement.js

Lines changed: 155 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,190 @@
11

2-
import { LitElement, html, css } from 'lit';
2+
import { LitElement, html, css, nothing } from 'lit';
33

44
/**
5-
* FormElement
5+
* FormElement is the base class for all form elements
66
*/
77
export class FormElement extends LitElement {
8+
#internals;
9+
810
constructor() {
911
super();
12+
13+
// Attach with the form
14+
this.#internals = this.attachInternals();
15+
1016
// Default properties
11-
this.name = 'wc-form';
12-
this.method = "POST";
13-
this.action = "#";
17+
this.name = this.textContent;
18+
this.value = '';
19+
this.description = '';
20+
this.placeholder = '';
21+
this.disabled = false;
22+
this.required = false;
23+
this.autocomplete = false;
24+
this.labelabove = false;
25+
}
26+
static get formAssociated() {
27+
return true;
1428
}
1529
static get properties() {
1630
return {
1731
/**
18-
* Name of the form
19-
* @type {String}
32+
* The name for the input
33+
* @type {string}
2034
*/
2135
name: { type: String },
2236

2337
/**
24-
* The method for submitting the form (POST or GET)
38+
* The value for the input
2539
* @type {string}
2640
*/
27-
method: { type: String },
41+
value: { type: String, reflect: true },
2842

2943
/**
30-
* The action when submitting the form
44+
* Description of the input
45+
*/
46+
description: { type: String },
47+
48+
/**
49+
* The placeholder text for the input
3150
* @type {string}
3251
*/
33-
action: { type: String },
52+
placeholder: { type: String },
53+
54+
/**
55+
* Whether the control is enabled
56+
* @type {boolean}
57+
*/
58+
disabled: { type: Boolean },
59+
60+
/**
61+
* Whether the input is required to be filled
62+
* for the form to submit
63+
* @type {boolean}
64+
*/
65+
required: { type: Boolean },
66+
67+
/**
68+
* Whether auto-complete is enabled
69+
* @type {boolean}
70+
*/
71+
autocomplete: { type: Boolean },
72+
73+
/**
74+
* Label position above, rather than to the left
75+
* @type {boolean}
76+
*/
77+
labelabove: { type: Boolean }
3478
};
3579
}
3680
static get styles() {
3781
return css`
38-
form {
39-
display: inline-block;
40-
width: 100%;
41-
margin: var(--form-margin);
82+
div {
83+
display: flex;
84+
justify-content: start;
85+
border: 1px solid red;
4286
}
43-
`;
87+
.labelbeside {
88+
flex-direction: row;
89+
}
90+
.labelabove {
91+
flex-direction: column;
92+
}
93+
div.description {
94+
flex-direction: column;
95+
color: var(--form-input-description-color);
96+
font-size: var(--form-input-description-font-size);
97+
font-weight: var(--form-input-description-font-weight);
98+
}
99+
.control {
100+
border: 1px solid red;
101+
flex: 1;
102+
background-color: var(--form-input-background-color);
103+
color: var(--form-input-color);
104+
margin: var(--form-input-margin-y) var(--form-input-margin-x) var(--form-input-margin-y) var(--form-input-margin-x);
105+
padding: var(--form-input-padding-y) var(--form-input-padding-x) var(--form-input-padding-y) var(--form-input-padding-x);
106+
font-family: inherit;
107+
font-size: var(--form-input-font-size);
108+
font-weight: var(--form-input-font-weight);
109+
line-height: var(--form-input-line-height);
110+
border: var(--form-input-border);
111+
}
112+
.control::placeholder {
113+
color: var(--form-input-placeholder-color);
114+
}
115+
.error {
116+
color: var(--form-input-error-color);
117+
}
118+
label {
119+
display: block;
120+
min-width: 10em;
121+
background-color: var(--form-label-background-color);
122+
color: var(--form-label-color);
123+
padding: var(--form-label-padding-y) var(--form-label-padding-x) var(--form-label-padding-y) var(--form-label-padding-x);
124+
font-size: var(--form-label-font-size);
125+
font-weight: var(--form-label-font-weight);
126+
line-height: var(--form-label-line-height);
127+
border: var(--form-label-border) solid red;
128+
}
129+
`;
130+
}
131+
_renderLabel() {
132+
if (this.innerHTML) {
133+
return html`<label for="${this.name}"><slot></slot></label>`;
134+
} else {
135+
return nothing;
136+
}
137+
}
138+
_renderInput() {
139+
return html`<input
140+
class="control"
141+
name=${this.name || nothing}
142+
value=${this.value || nothing}
143+
?required=${this.required}
144+
?disabled=${this.disabled}
145+
placeholder=${this.placeholder || nothing}
146+
autocomplete=${this.autocomplete ? 'on' : 'off'}
147+
@input=${this._updateValue}
148+
>`;
149+
}
150+
_renderDescription() {
151+
if (this.validationMessage) {
152+
return html`<span class="error">${this.validationMessage}</span>`;
153+
} else if (this.description) {
154+
return html`<span>${this.description}</span>`;
155+
} else {
156+
return nothing;
157+
}
44158
}
45159
render() {
160+
const renderLabel = this._renderLabel();
161+
const renderInput = this._renderInput();
162+
const renderDescription = this._renderDescription();
46163
return html`
47-
<form method="${this.method}" name="${this.name}" action="${this.action}" @submit=${this.onSubmit}>
48-
<slot></slot>
49-
</form>
50-
`;
164+
<div class="${this.labelabove ? 'labelabove' : 'labelbeside'}">
165+
${renderLabel}
166+
<div class="description">
167+
${renderInput}
168+
${renderDescription}
169+
</div>
170+
</div>
171+
`;
51172
}
52-
submit() {
53-
if(this.shadowRoot) {
54-
this.shadowRoot.querySelector('form').submit();
173+
174+
// Form control properties
175+
get form() { return this.#internals ? this.#internals.form : null; }
176+
get type() { return this.localName; }
177+
get validity() { return this.#internals ? this.#internals.validity : null; }
178+
get validationMessage() { return this.#internals ? this.#internals.validationMessage : null; }
179+
get willValidate() { return this.#internals ? this.#internals.willValidate : null; }
180+
181+
// Callbacks
182+
_updateValue(event) {
183+
if (!this.disabled) {
184+
this.value = event.target.value;
185+
this.#internals.setFormValue(this.value);
55186
}
56187
}
57-
onSubmit(event) {
58-
event.preventDefault();
59-
console.log('Form submitted');
60-
}
61188
}
62189

63-
customElements.define('wc-form', FormElement);
190+
customElements.define('wc-form-input', FormElement);

src/component/form/FormElement.js-OLD

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
2+
import { LitElement, html, css } from 'lit';
3+
4+
/**
5+
* FormElement
6+
*/
7+
export class FormElement extends LitElement {
8+
constructor() {
9+
super();
10+
// Default properties
11+
this.name = 'wc-form';
12+
this.method = "POST";
13+
this.action = "#";
14+
}
15+
static get properties() {
16+
return {
17+
/**
18+
* Name of the form
19+
* @type {String}
20+
*/
21+
name: { type: String },
22+
23+
/**
24+
* The method for submitting the form (POST or GET)
25+
* @type {string}
26+
*/
27+
method: { type: String },
28+
29+
/**
30+
* The action when submitting the form
31+
* @type {string}
32+
*/
33+
action: { type: String },
34+
};
35+
}
36+
static get styles() {
37+
return css`
38+
form {
39+
display: inline-block;
40+
width: 100%;
41+
margin: var(--form-margin);
42+
}
43+
`;
44+
}
45+
render() {
46+
return html`
47+
<form method="${this.method}" name="${this.name}" action="${this.action}" @submit=${this.onSubmit}>
48+
<slot></slot>
49+
</form>
50+
`;
51+
}
52+
submit() {
53+
if(this.shadowRoot) {
54+
this.shadowRoot.querySelector('form').submit();
55+
}
56+
}
57+
onSubmit(event) {
58+
event.preventDefault();
59+
console.log('Form submitted');
60+
}
61+
}
62+
63+
customElements.define('wc-form', FormElement);

0 commit comments

Comments
 (0)