I am writing code that uses data binding to change the innerHTML
of an span
to the input of the user, but I can’t get it to work. What it should do is show the input on the right side of the input field on both the input fields, but it doesn’t. Can someone please help me out.
HTML:
<html lang="en-US"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>My Frontend Framework</title> </style> </head> <body> <div> <label>Name:</label> <input type="text" bit-data="name"/> <span bit-data-binding="name" style="margin-left: 1rem;"></span> </div> <div> <label>Lastname:</label> <input type="text" bit-data="LastName"/> <span bit-data-binding="LastName" style="margin-left: 1rem;"></span> </div> <script src="frontend-framework.js"></script> </body> </html>
Javascript:
const createState = (stateObj) => { return new Proxy(stateObj, { set(target, property, value) { target[property] = value; render(); return true; } }); }; const state = createState({ name: '', lastName: '' }); const listeners = document.querySelectorAll('[bit-data]'); listeners.forEach((element) => { const name = element.dataset.model; element.addEventListener('keyup', (event) => { state[name] = element.value; console.log(state); }); }); const render = () => { const bindings = Array.from(document.querySelectorAll('[bit-data-binding]')).map( e => e.dataset.binding ); bindings.forEach((binding) => { document.querySelector(`[bit-data-binding=${binding}]`).innerHTML = state[binding]; document.querySelector(`[bit-data=${binding}]`).value = state[binding]; }); }
https://jsfiddle.net/Mauro0294/g3170whc/4/
Advertisement
Answer
I made some changes to the fiddle to get the desired result. The problem was with your logic to refer the elements using the dataset
attributes, so I tried to simplify it.
Some notable changes :
- Updated the
data-bit
to uselastName
instead ofLastName
. Made it same as your state. - Used
getAttribute
to get the value of thedata-*
properties to correctly get the reference.
I think this is what you’re looking for:
const createState = (stateObj) => { return new Proxy(stateObj, { set(target, property, value) { target[property] = value; render(); return true; } }); }; const state = createState({ name: '', lastName: '' }); const listeners = document.querySelectorAll('[bit-data]'); listeners.forEach((element) => { const name = element.getAttribute('bit-data'); console.log('here', element.getAttribute('bit-data'), JSON.stringify(element.dataset)) element.addEventListener('keyup', (event) => { state[name] = element.value; console.log(state); }); }); const render = () => { const bindings = Array.from(document.querySelectorAll('[bit-data-binding]')).map((e) => { return e.getAttribute('bit-data-binding'); }); //console.log('bindings:', bindings, document.querySelectorAll('[bit-data-binding]')); (bindings ?? []).forEach((binding) => { document.querySelector(`[bit-data-binding=${binding}]`).innerHTML = state[binding]; document.querySelector(`[bit-data=${binding}]`).value = state[binding]; }); }
<html lang="en-US"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>My Frontend Framework</title> </head> <body> <div> <label>Name:</label> <input type="text" bit-data="name"/> <span bit-data-binding="name" style="margin-left: 1rem;"></span> </div> <div> <label>Lastname:</label> <input type="text" bit-data="lastName"/> <span bit-data-binding="lastName" style="margin-left: 1rem;"></span> </div> </body> </html>