skip to Main Content

I’m currently making a website with a "shopping list" functionality. I can create an array and add items to the "shopping list" via the input field, and I can also remove the latest input using a button.
As of now, the list shows all new items in order of input. But, when I remove the latest item, it shows only that item. And then when I add a new item, the full, updated list shows.

These pictures show how it currently looks:

  1. Add items, that show up in the list ¨
    enter image description here
  2. Remove item – the list disappears and only the latest item being removed is shown
    enter image description here
  3. The new, updated list shows ONLY after I’ve added a new item to the list ("four")
    enter image description here

What I’m trying to do is this:

  1. Add items – they show up in the list, as now
    enter image description here
  2. Remove item – the latest item is just removed from the list, but the list still shows previous items remaining. The picture here is how I want it to look.

enter image description here

  1. Add new items again – they get added to the list in order of input as it looks in the picture.
    enter image description here
var arrayOfWord = [];
var inputElement = document.getElementById('userinput');
var errorElement = document.getElementById('error');
var wordsElement = document.getElementById('words');

function addWord() {
  errorElement.innerHTML = "";
  var word = inputElement.value;
  if (word.trim() === "")
    errorElement.innerHTML = "Empty input, write an item you want to put on the list!";
  else
    arrayOfWord.push(word);
  inputElement.value = "";
  process();
}

function process() {
  words.innerHTML = arrayOfWord.join(' <br><br> ');
}

function remove() {
  words.innerHTML = arrayOfWord.pop();
  document.getElementById('words').innerHTML = parsed;
}
<p>
  <ol id="demo"></ol>
</p>

<input id="userinput" /><button onclick="addWord()">Add item</button>
<div id="error"></div>
<button onclick="remove()">Remove</button><br>

<p id="testing"></p>
<p id="words"></p><br>

<a href="#" class="action">Buy Now</a>
</div>

3

Answers


  1. The issue is because of this line in remove():

    words.innerHTML = arrayOfWord.pop();
    

    That is removing the last item from the array, but it then sets that item, which has been removed from your array, as the visible text within the element.

    To fix the problem call pop() without setting the HTML of the element directly, then call your process() function to update the DOM based on the
    new content of the array:

    function remove() {
      arrayOfWord.pop();
      process();
    }
    

    Here’s a full working example:

    var arrayOfWord = [];
    var inputElement = document.getElementById('userinput');
    var errorElement = document.getElementById('error');
    var wordsElement = document.getElementById('words');
    
    function addWord() {
      errorElement.innerHTML = "";
      var word = inputElement.value;
      if (word.trim() === "")
        errorElement.innerHTML = "Empty input, write an item you want to put on the list!";
      else
        arrayOfWord.push(word);
      inputElement.value = "";
      process();
    }
    
    function process() {
      words.innerHTML = arrayOfWord.join(' <br><br> ');
    }
    
    function remove() {
      arrayOfWord.pop();
      process();
    }
    <p>
      <ol id="demo"></ol>
    </p>
    <input id="userinput" /><button onclick="addWord()">Add item</button>
    <div id="error"></div>
    <button onclick="remove()">Remove</button><br>
    
    <p id="testing"></p>
    <p id="words"></p><br>
    
    <a href="#" class="action">Buy Now</a>
    </div>

    Also, as a side note, be aware that ol elements are not valid within p (further reading on this here), and it’s much better practice to bind your event handlers unobtrusively in JS using addEventListener() instead of using onX attributes in your HTML.

    Login or Signup to reply.
  2. The problem you are facing is most probably because of arrayOfWord.pop() method in function remove. You are assigning the value of arrayOfWord.pop() to words.innerHTML , which eventually returns the deleted element not the the whole array.

    To fix this issue you can think of another approach like re rendering the whole array as updated result
    Use pop method but don’t render it to your page . Hope this will work for you

    Login or Signup to reply.
  3. It is generally not a good idea to use inline event handlers. Furthermore, I’d say the interface is not so clear. How would a user know what the remove button does? Wouldn’t it be an idea to enable removing one of all items instead of the last added?

    With that in mind I suggest something like this (using event delegation and a factory function for the handling):

    document.addEventListener(`click`, handle);
    document.addEventListener(`keyup`, handle);
    const actions = actionFactory();
    
    function handle(evt) {
      const action = evt.target.dataset.action;
      
      if (action && action in actions) {
        return actions[action](evt);
      }
    }
    
    function actionFactory() {
      const addBttn = document.querySelector(`[data-action='add']`);
      const userInput = document.querySelector(`#userinput`);
      const errorElem = document.querySelector(`#error`);
      const words = document.querySelector(`#words`);
      let selectedWords = [];
      
      return {
        enter: function(evt) {
          if(evt.key === 'Enter') {
            return addBttn.click();
          }
        },
        add: function() {
          const inputValue = userInput.value.trim();
          
          if (inputValue.length < 1) {
            errorElem.textContent = "please fill out with some text";
            return setTimeout(_ => errorElem.textContent = ``, 2000);
          }
          
          selectedWords.push(inputValue);
          // add the word to the words-element
          words.insertAdjacentHTML(
          `beforeend`,
          `<div>
             <span>${inputValue}</span> 
             <button data-action="remove">remove</button>
           </div>`);
          return userInput.value = ``;
        },
        remove: function(evt) {
          const wordElem = evt.target.closest(`div`);
          const word = wordElem.querySelector(`span`).textContent;
          // re-assign the array, filtering out the word to remove
          selectedWords = selectedWords.filter(wrd => wrd !== word);
          return wordElem.remove();
        }
      }
    }
    #error {
      display: inline-block;
      margin-left: 0.3rem;
      color: red;
    }
    
    #words {
      div {
        margin-bottom: 0.2rem;
      }
      div:nth-child(even) {
        background-color: #EEE;
      }
      div > span {
        display: inline-block;
        position: relative;
        width: 177px;
      }
    }
    <input id="userinput" 
      placeholder="type something" 
      data-action="enter">
    <button data-action="add">Add item</button>
    <span id="error"></span>
    <p id="words"></p>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search