How to reference a JS item from a DOM element

Asked

Viewed 118 times

0

I am making a To from the List using MVC, I have an array that saves the tasks added by the user and from this array I create elements in DOM. Can I reference the specific item of the array from a click on the DOM? For example, how can I delete an item from the list when its DOM element is deleted? I tried the code below, using ${task} to pass the object I want to change, but it doesn’t work because the element is no longer a reference to the object. Is there any other way to change the specific object?

return array.lista.map(tarefa => {
  return `<button onclick='controller.conclui(event, ${tarefa})'></button>`
}).join('');

Edit. I understand, I would have to pass an indenter to get a reference to the object I want to edit, but would there be any way to get a direct reference? as is possible with React, for example:

       {tarefas.map(tarefa => (
        <button
          type="button"
          onClick={event => onButtonClick(event, tarefa)}
          key={tarefa}
        >
         {tarefa.classe} 
        </button>

      ))}

because in this case I can access the properties of my 'task' object directly, but I don’t know if it has to achieve this effect with pure js

4 answers

1

The problem with its function is that it is being generated from a string.

A string has no way to store a reference to its task array, you would need to store some type of identifier (a number or a string) in your task, and use that identifier to find the task in your array.

Example:

array.lista.map(tarefa =>
    `<button onclick='conclui(event, ${tarefa.id})'></button>`
).join('');

function conclui(event, id) {
    // encontra a tarefa com o id recebido
    var tarefa = array.lista.find(tarefa => tarefa.id === id);
    tarefa.concluida = true;
}


The other option would be not to generate your function through a string, but from code, so yes you could send an object as parameter

var botoes = array.lista.map(tarefa => {
    var button = document.createElement('button');
    button.onclick = (event) => conclui(event, tarefa);
    return button;
});

function conclui(event, tarefa) {
    // ...
}

1

As already warned, there is no way to pass the object in the template string, but Voce can pass the id and redo its function concludes.

So you could use de-structuring to get the id and move on to the method:

array.map( ({id}) => ( 
  <button onclick = "conclui(${id})">Remover Tarefa</button>)

).join('')

0


I got the effect I wanted with the following code:

const app = document.getElementById("app");
const tarefas = ["tarefa1", "tarefa2", "tarefa3"];

app.innerHTML = `
<h1>Hello Vanilla!</h1>
<div>
  Exemplo
</div>
`;

tarefas.forEach(tarefa => {
  const button = document.createElement("button");

  button.innerHTML = `Click ${tarefa}`;
  button.onclick = function() {
    console.log("to aqui no onclick", tarefa);
  };

  app.appendChild(button);

0

Yes, you can pass this as argument, or use this event and read the property target which will be the element of the DOM clicked.

Would that be:

const controller = {
  conclui(evento, button, algo) {
    console.log(button.tagName, evento.target === button); // true
  }
};
<button type="button" onclick='controller.conclui(event, this, "${tarefa}")'>
                        Clica-me!</button>

  • The problem I’m encountering with this code is that the task object is passed as a string, and I was wondering if you have any way to get a direct reference without having to use indenters

  • @Josésantos what is the value of this tarefa?

  • I don’t know if I understand, but this task is a js object

  • @Josésantos I thought you wanted a reference to button, that’s what I answered. Isn’t that what you wanted? This tasks object, if it’s a string you can do JSON.parse() inside controller.conclui to convert into object...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.