Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

[Dúvida] Duplicação dos itens ao adicionar a lista

Efetuei a resolução do projeto, porém ele esta duplicando os itens conforme eu os adiciono, e não estou encontrando aonde possa estar o erro.

const form = document.getElementById("novoItem") 
const lista = document.getElementById("lista")
const itens = JSON.parse(localStorage.getItem("itens")) || []  

// MANTENDO OS ITENS CRIADOS NA PÁGINA, MESMO APÓS ATUALIZAR
itens.forEach( (elemento) => {    
    criaElemento(elemento)
} )

form.addEventListener("submit", (evento) => {  
    evento.preventDefault()

    const nome = evento.target.elements['nome']
    const quantidade = evento.target.elements['quantidade']

    // VERIFICANDO A EXISTENCIA DOS ITENS
    const existe = itens.find( elemento => elemento.nome === nome.value )

    // CRIA UM ARRAY PARA NOME E QUANTIDADE
    const itemAtual = {
    "nome": nome.value,
    "quantidade": quantidade.value
    }

    criaElemento(itemAtual)

    itens.push(itemAtual)


// Condicional para conferir se o elemento 

if (existe) {
    itemAtual.id = existe.id

    atualizaElemento(itemAtual)
//Refatoração da condicional if else, atualizando um id para cada item
    itens[itens.findIndex(elemento => elemento.id === existe.id)] = itemAtual
} else {
    itemAtual.id = itens[itens.length -1] ? (itens[itens.length-1]).id + 1 : 0;

    criaElemento(itemAtual)

    itens.push(itemAtual)
}

localStorage.setItem("itens", JSON.stringify(itens))

nome.value = ""
quantidade.value = ""
})

    // TRANSFORMA O "ITENS" EM STRING, VISTO QUE O LOCAL STORAGE APENAS ENTENDE ELEMENTOS DE TEXTOS (STRINGS)
    localStorage.setItem("itens", JSON.stringify(itens))

    // DEIXA OS ARRAYS VAZIOS ASSIM QUE UM NOVO ITEM É ADICIONADO
    nome.value = ""
    quantidade.value = ""

function criaElemento(item) {  

    // CRIA UMA 'LI' QUE GUARDARÁ OS ITENS
    // DA UMA CLASSE PARA A LI CRIADA 
    const novoItem = document.createElement('li')
    novoItem.classList.add("item")

    // CRIA UM ELEMENTO STRONG PARA A QUANTIDADE
    const numeroItem = document.createElement('strong')

    // FAZ COM QUE O ELEMENTO numeroItem RECEBA A ID DE QUANTIDADE
    // LOGO NA PÁGINA, O numeroItem FICARÁ NO CAMPO DE input QUANTIDADE RECEBENDO O VALOR NUMÉRICO
    numeroItem.innerHTML = item.quantidade

    // PEGARÁ O DATASET DO ID NO HTML
    numeroItem.dataset.id = item.id

    // o appendChild INFILTRA UM ITEM DENTRO DE OUTRO NO HTML, NESSE CASO COLOCANDO A TAG STRONG DENTRO DA CONST = novoItem
    novoItem.appendChild(numeroItem)

    // FAZ COM QUE O NOME DO ITEM VENHA APÓS O NUMERO
    novoItem.innerHTML += item.nome

    // Referenciar a função botaoDeleta no nó da função principal
    novoItem.appendChild(botaoDeleta(item.id)) 

        /*OBS: ADICIONE O ID LISTA NO DOCUMENTO HTML PARA FUNCIONAR
    criaremos uma const = lista para armazenar o id 'lista' no HTML, ficando assim:

    const lista = document.getElementById('lista')

    podemos tirar essa const do escopo da função, pois o código abaixo irá chamar essa const lista
    e ela continuará funcionando mesmo fora da function.
    */

    // AQUI SERÁ ADICIONADO TUDO O QUE FOI FEITO ACIMA Á PÁGINA, PARA QUANDO DER O SUBMIT
    // CRIAR UM NOVO ITEM COM A QUANTIDADE E NOME E COM O ESTILO CONFORME O CSS E HTML.
    lista.appendChild(novoItem)


function atualizaElemento(item) {
    document.querySelector("[data-id='"+item.id+"']").innerHTML = item.quantidade
}

//Função para criar botão com evento de click nos itens, e retornar os itens clicados
function botaoDeleta(id) {
    const elementoBotao = document.createElement("button")
    elementoBotao.innerText = "X"

    elementoBotao.addEventListener("click", function() {
        deletaElemento(this.parentNode, id)
    })

    return elementoBotao
}

//Função para deletar os itens enviados da função botaoDeleta no array de itens e no navegador

function deletaElemento(tag, id) { 
    tag.remove()

    itens.splice(itens.findIndex(elemento => elemento.id === id), 1)

    localStorage.setItem("itens", JSON.stringify(itens))
}
}

function atualizaElemento(item) {
    document.querySelector("[data-id='"+item.id+"']").innerHTML = item.quantidade
}
1 resposta
solução!

Olá André, tudo bem?

O problema de duplicação de itens estar ocorrendo porque a função criaElemento(itemAtual) está sendo chamada duas vezes, uma antes do if (existe) e outra dentro do else.

Para corrigir o problema de duplicação, você pode remover a linha criaElemento(itemAtual) dentro do else, desse modo o erro de duplicação é reparado.

Seu código reparado e funcional fica assim:

const form = document.getElementById("novoItem") 
const lista = document.getElementById("lista")
const itens = JSON.parse(localStorage.getItem("itens")) || []  

// MANTENDO OS ITENS CRIADOS NA PÁGINA, MESMO APÓS ATUALIZAR
itens.forEach( (elemento) => {    
    criaElemento(elemento)
} )

form.addEventListener("submit", (evento) => {  
    evento.preventDefault()

    const nome = evento.target.elements['nome']
    const quantidade = evento.target.elements['quantidade']

    // VERIFICANDO A EXISTENCIA DOS ITENS
    const existe = itens.find( elemento => elemento.nome === nome.value )

    // CRIA UM ARRAY PARA NOME E QUANTIDADE
    const itemAtual = {
    "nome": nome.value,
    "quantidade": quantidade.value
    }

    criaElemento(itemAtual)

    itens.push(itemAtual)


// Condicional para conferir se o elemento 

if (existe) {
    itemAtual.id = existe.id

    atualizaElemento(itemAtual)
//Refatoração da condicional if else, atualizando um id para cada item
    itens[itens.findIndex(elemento => elemento.id === existe.id)] = itemAtual
} else {
    itemAtual.id = itens[itens.length -1] ? (itens[itens.length-1]).id + 1 : 0;

    /*Linha excluída na qual chamava a função  criaElemento(itemAtual) */

    itens.push(itemAtual)
}

localStorage.setItem("itens", JSON.stringify(itens))

nome.value = ""
quantidade.value = ""
})

    // TRANSFORMA O "ITENS" EM STRING, VISTO QUE O LOCAL STORAGE APENAS ENTENDE ELEMENTOS DE TEXTOS (STRINGS)
    localStorage.setItem("itens", JSON.stringify(itens))

    // DEIXA OS ARRAYS VAZIOS ASSIM QUE UM NOVO ITEM É ADICIONADO
    nome.value = ""
    quantidade.value = ""

function criaElemento(item) {  

    // CRIA UMA 'LI' QUE GUARDARÁ OS ITENS
    // DA UMA CLASSE PARA A LI CRIADA 
    const novoItem = document.createElement('li')
    novoItem.classList.add("item")

    // CRIA UM ELEMENTO STRONG PARA A QUANTIDADE
    const numeroItem = document.createElement('strong')

    // FAZ COM QUE O ELEMENTO numeroItem RECEBA A ID DE QUANTIDADE
    // LOGO NA PÁGINA, O numeroItem FICARÁ NO CAMPO DE input QUANTIDADE RECEBENDO O VALOR NUMÉRICO
    numeroItem.innerHTML = item.quantidade

    // PEGARÁ O DATASET DO ID NO HTML
    numeroItem.dataset.id = item.id

    // o appendChild INFILTRA UM ITEM DENTRO DE OUTRO NO HTML, NESSE CASO COLOCANDO A TAG STRONG DENTRO DA CONST = novoItem
    novoItem.appendChild(numeroItem)

    // FAZ COM QUE O NOME DO ITEM VENHA APÓS O NUMERO
    novoItem.innerHTML += item.nome

    // Referenciar a função botaoDeleta no nó da função principal
    novoItem.appendChild(botaoDeleta(item.id)) 

        /*OBS: ADICIONE O ID LISTA NO DOCUMENTO HTML PARA FUNCIONAR
    criaremos uma const = lista para armazenar o id 'lista' no HTML, ficando assim:

    const lista = document.getElementById('lista')

    podemos tirar essa const do escopo da função, pois o código abaixo irá chamar essa const lista
    e ela continuará funcionando mesmo fora da function.
    */

    // AQUI SERÁ ADICIONADO TUDO O QUE FOI FEITO ACIMA Á PÁGINA, PARA QUANDO DER O SUBMIT
    // CRIAR UM NOVO ITEM COM A QUANTIDADE E NOME E COM O ESTILO CONFORME O CSS E HTML.
    lista.appendChild(novoItem)


function atualizaElemento(item) {
    document.querySelector("[data-id='"+item.id+"']").innerHTML = item.quantidade
}

//Função para criar botão com evento de click nos itens, e retornar os itens clicados
function botaoDeleta(id) {
    const elementoBotao = document.createElement("button")
    elementoBotao.innerText = "X"

    elementoBotao.addEventListener("click", function() {
        deletaElemento(this.parentNode, id)
    })

    return elementoBotao
}

//Função para deletar os itens enviados da função botaoDeleta no array de itens e no navegador

function deletaElemento(tag, id) { 
    tag.remove()

    itens.splice(itens.findIndex(elemento => elemento.id === id), 1)

    localStorage.setItem("itens", JSON.stringify(itens))
}
}

function atualizaElemento(item) {
    document.querySelector("[data-id='"+item.id+"']").innerHTML = item.quantidade
}

Espero ter ajudado, qualquer dúvida, me coloco à disposição! Bons estudos!

Sucesso

Um grande abraço e até mais!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓. Bons Estudos!