Is there a way to two-way bind an attribute of a custom HTML element in Blazor? I have a custom element with a value attribute linked to a text input internally that I'd like to bind the value of.
<template id="text"><div style="height:40px; width:100%; display:flex; flex-direction:column; justify-content:center; align-items:flex-start; padding:10px"><label for="textline" style="padding-left:5px"><slot name="label"></slot></label><input type="text" id="textline" style="border:solid 2px lightgrey; border-radius:5px; padding:5px; font-family:Montserrat; height:100%; font-size:15px; width:100%; box-sizing: border-box;" /></div></template>Here's the JS defining the custom element:
customElements.define("bonsai-text-box",class extends HTMLElement { static observedAttributes = ["label", "value"]; constructor() { super(); } async connectedCallback() { let html = await fetch("https://nexusdockapidev.ctdi.com/GetBonsaiHTML"); let json = await html.json(); let div = document.createElement('div'); div.innerHTML = json.html; this.appendChild(div); let template = document.getElementById("text"); let templateContent = template.content; const label = this.getAttribute("label"); const labelSpan = document.createElement("span"); labelSpan.setAttribute("slot", "label"); labelSpan.setAttribute("id", "labelspan"); labelSpan.innerHTML = label; const shadowRoot = this.attachShadow({ mode: "open" }); let css = await fetch("https://nexusdockapidev.ctdi.com/GetBonsaiCSS"); let cssjson = await css.json(); let style = document.createElement('style'); style.innerHTML = cssjson.css; shadowRoot.appendChild(style); shadowRoot.appendChild(templateContent.cloneNode(true)); this.appendChild(labelSpan); this.inputNode = this.shadowRoot.querySelector('input') this.inputNode.addEventListener("change", (e) => { this.setAttribute("value", e.target.value); }); } get value () { return this.inputNode.value } set value (newValue) { this.inputNode.value = newValue } attributeChangedCallback(name, oldValue, newValue) { if (name === "label") { const oldlabelspan = this.querySelector("#labelspan"); if (oldlabelspan) { oldlabelspan.parentNode.removeChild(oldlabelspan); const labelSpan = document.createElement("span"); labelSpan.setAttribute("slot", "label"); labelSpan.setAttribute("id", "labelspan"); labelSpan.innerHTML = newValue; this.appendChild(labelSpan); this.dispatchEvent(new Event("change")); } } else if (name === 'value') { this.inputNode.value = newValue; } }},);
I've tried @bind and @bind-value and neither seem to work how I expect.