Am using Lit2.0, Material Web components, Django (backend).
one reference: https://www.thinktecture.com/en/web-components/flaws/
I don't understand how to submit form data from Lit component to backend (Django)
form.html contains Lit component (basic-form)
<form id="id_demo" method="post" action="">
{% csrf_token %}
<basic-form></basic-form>
<button type="submit" class="mdc-button mdc-button--raised">Submit</button>
</form>
basic-form is a Lit component and it contains Material web components
import {LitElement, html} from "lit";
// const template = document.createElement('template');
// template.innerHTML = `
// <slot></slot>
// `;
export class BasicForm extends LitElement {
static properties = {
form: '',
};
constructor() {
super();
// this.shadow = this.attachShadow({ mode: 'open' });
// this.shadow.appendChild(template.content.cloneNode(true));
}
render() {
return html`
<mwc-textfield name="first_name"></mwc-textfield>
`;
}
}
customElements.define('basic-form', BasicForm);
Could someone guide me to the right direction.
You can take the value of textfield element on blur and save it as property of basic-form. Then on form submit you can take the basic-form.value property:
basic-form
export class BasicForm extends LitElement {
static properties = {
value: ''
}
onBlur() {
this.value = e.target.value;
}
render() {
return html`
<mwc-textfield name="first_name" @onBlur="${this.onBlur}></mwc-textfield>
`;
}
form.html
<form id="id_demo" method="post" action="">
{% csrf_token %}
<basic-form></basic-form>
<button type="submit" class="mdc-button mdc-button--raised">Submit</button>
</form>
<script>
const form = document.getElementById("id_demo");
const basicForm = form.querySelector('basic-form');
const onSubmit = (event) => {
console.log(basicForm.value);
}
form.addEventListener('submit', onSubmit);
</script>
Actually this is not that easy at all. You have to use ElementInternals: https://developer.mozilla.org/en-US/docs/Web/API/ElementInternals
"The ElementInternals interface of the Document_Object_Model gives web developers a way to allow custom elements to fully participate in HTML forms."
That said here is an example:
<script type="module">
import {
LitElement,
html,
css
} from "https://unpkg.com/lit-element/lit-element.js?module";
class MyItem extends LitElement {
static get formAssociated() {
return true;
}
static get properties() {
return {
name: { type: String, reflect: true },
required: { type: Boolean, reflect: true },
value: { type: String }
};
}
constructor() {
super();
this.internals = this.attachInternals();
this.name = name;
this.required = false;
this.value = '';
this._required = false;
}
render() {
return html`
<label for="input"><slot></slot></label>
<input type="${this.type}" name="${this.name}" id="input" .value="${this.value}" ?required="${this.required}" @input="${this._onInput}">
`;
}
_onInput(event) {
this.value = event.target.value
this.internals.setFormValue(this.value);
}
firstUpdated(...args) {
super.firstUpdated(...args);
/** This ensures our element always participates in the form */
this.internals.setFormValue(this.value);
}
}
customElements.define("my-item", MyItem);
const formElem = document.querySelector('#formElem');
formElem.addEventListener('submit', event => {
event.preventDefault();
const form = event.target;
/** Get all of the form data */
const formData = new FormData(form);
formData.forEach((value, key) => console.log(`${key}: ${value}`));
});
</script>
<form id="formElem">
<my-item name="firstName">First name</my-item>
<button type="submit">Submit</button>
</form>