2

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.

Yogi
  • 21
  • 1
  • 1

2 Answers2

1

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>
Christian
  • 3,503
  • 1
  • 26
  • 47
0

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>
jorgecasar
  • 641
  • 5
  • 8