Home > Net >  Javascript Dynamic Data binding code not working
Javascript Dynamic Data binding code not working

Time:12-15

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/

CodePudding user response:

Your main issue is this part:

const bindings = Array.from(document.querySelectorAll('[bit-data-binding]')).map(
    e => e.dataset.binding
  );

or more specifically e.dataset.binding. Your elements do not a have data-binding attribute, which would be the prerequisite for using dataset.binding. You can use e.getAttribute('bit-data-binding') instead.

But your logic is also flawed: As it currently stands, entering text into an input is pointless, as the state is never updated.

Finally, note that you spell LastName with a capital L in your DOM but lowercased in your state object.

CodePudding user response:

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 :

  1. Updated the data-bit to use lastName instead of LastName. Made it same as your state.
  2. Used getAttribute to get the value of the data-* 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>

  • Related