0

I am using lit-html and I can't seem to get the renderer to update, or any function to run on user input. I would like to check an input field on typing. I can't find any examples online showing responding to user input.

Here is the full code.

my_input.ts

import {html, directive, Part} from 'lit-html';

const stateMap = new WeakMap();
export const stateManager = directive(() => (part: Part) => {
    let mystate: IInputData = stateMap.get(part);
    if(mystate === undefined)
    {
        mystate = {
            auto_id: Math.floor(Math.random() * 100000 + 1),
            helper_eval: "",
            input_message: "",
            tab_index: 0,
            input_value: "",
            span_message: "",
        }
        stateMap.set(part, mystate);
    }
    else {
        console.log("Hey");
        part.setValue(mystate);
        part.commit();
    }
});
export interface IInputData {
    auto_id: number,
    helper_eval: string,
    input_message: string,
    tab_index: number,
    input_value: string,
    span_message: string
}
export let my_input = () => {
    let d: IInputData = stateManager() as unknown as IInputData;
    return html`
    <section>
        <label for="${d.auto_id}" 
            title="${d.helper_eval}">
            ${d.input_message} &#x24D8
            <span class="float_left">
            ${d.span_message}
            </span>
        </label>
        <input id="${d.auto_id}" 
            tabindex="${d.tab_index}" value="${d.input_value}">
        </input>
    <section>
    `;
}

app.ts


const myTemplate = () => html`
  <div>
    ${renderCounter(0)}
  </div>`;

const renderCounter = directive((initialValue) => (part: any) => {
    if(part.value === undefined)
    {
        part.setValue(initialValue);
    }
    else { part.setValue(part.value +1)}
  }
 );
export let app = (data: TemplateResult[]) => html`
        ${data}
    `;
render(app([my_input(), myTemplate]), document.body);

I have included the render counting example, and don't see the render counter increase while typing in the input field. I am also not sure how I can add hooks to respond to the IInputData that change in that template. My best guess is to add some sort of callback function to the stateManager directive.

1 Answers1

0

If you are looking for a basic usage of lit-html, please read on. If you are trying to figure out how to implement a custom directive, then I hope someone else can answer it for you. Also, I don't know Typescript so my answer below is in a plain JavaScript.

The idea behind lit-html is for you to call render() function every time you want to update the HTML. It does not self-update its output.

So, to use it with an input element, you need to implement a callback function to update template's dependent data-structure and to re-render. The callback must be attached to your template with @input/@change/@click etc.

Here is a simple example (loosely based on yours):

// create a data object containing the template variables
const data = {
  span_message: "input text copy appears here"
}

// callback function for the input event
const inputCallback = (evt) => {
  // update the template data
  d.span_message = evt.target.value;
  // re-render the template
  render(myTemplate(data), document.body);
 };

// function to generate a template 
// d - data object, which controls the template
const myTemplate = (d) => html`
  <input 
    @input=inputCallback
  </input>
<span>
  ${d.span_message}
</span>`;

// initial rendering of the template
render(myTemplate(data), document.body);

Hope this helps

kesh
  • 4,515
  • 2
  • 12
  • 20