2

Instead of adding the item to the list using an add button and then removing the appended item using a remove button, how do I make them the same button (or input) so that if it is checked the item is appended to the list and if it is unchecked it is removed from the list?

I need the add and remove to be the same button so that I can remove the item from the list by either unchecking the item button OR the appended item's button.

// Wish Function
var wish = {
  items: []
};
var update_product = function(product) {};
$(function() {
  //Add to wish
  var addToWish = function(product, qty) {
    qty = qty || 1;
    var wish = getWish();
    var indexOfId = wish.items.findIndex(x => x.id == product.id);
    if (indexOfId === -1) {
      wish.items.push({
        id: product.id,
        img: product.img,
        name: product.name,
      });
      $parent = $("#" + product.id).closest(".items__wish");
      $parent
        .find(".wish-icon")
        .addClass("active")
        .attr("data-prefix", "fas");
    } else {
      wish.items[indexOfId].qty++;
      wish.items[indexOfId].stock = Number(product.stock);
    }
    //Update popup wish
    updateWish(wish);
  };

  var getProductValues = function(element) {
    var productId = $(element)
      .closest(".items__wish")
      .find(".item__tile")
      .attr("id");
    var productImg = $(element)
      .closest(".items__wish")
      .find(".item__img")
      .attr("src");
    var productName = $(element)
      .closest(".items__wish")
      .find(".item__title")
      .html();
    return {
      id: productId,
      img: productImg,
      name: productName,
    };
  };
  $(".my-wish-add").on("change", function() {
    var product = getProductValues(this);
    addToWish({
      id: product.id,
      img: product.img,
      name: product.name,
    });
  });
  //Update wish html to reflect changes
  var updateWish = function(wish) {
    //Add to shopping wish dropdown
    $(".wishlist__items").html("");
    for (var i = 0; i < wish.items.length; i++) {
      $(".wishlist__items").append(
        "<li>" +
        '<div class="my-wish-item">' +
        "<img src='" +
        wish.items[i].img +
        "' />" +
        '<div class="wish-main">' +
        '<div class="wish-name">' +
        wish.items[i].name +
        "</div>" +
        '<div class="my-wish-remove-container">' +
        '<input type="checkbox" id="my-wish-remove' +
        i +
        '" class="my-wish-remove" aria-hidden="true">' +
        "<i class='fas fa-heart'></i>" +
        "</div>"
      );
      //Remove from wish on id
      var removeFromWish = function(id) {
        var wish = getWish();
        var wishIndex = wish.items.findIndex(x => x.id == id);
        wish.items.splice(wishIndex, 1);
        $parent = $("#" + id).closest(".items__wish");
        $parent
          .find(".wish-icon")
          .first()
          .removeClass("active")
          .attr("data-prefix", "far");
        //Update popup wish
        updateWish(wish);
      };
      (function() {
        var currentIndex = i;
        $("#my-wish-remove" + currentIndex).on("change", function() {
          $(this)
            .closest("li")
            .hide(400);
          setTimeout(function() {
            wish.items[currentIndex].stock = "";
            update_product(wish.items[currentIndex]);
            removeFromWish(wish.items[currentIndex].id);
          }, 400);
        });
      })();
    }
  };
  //Get Wish
  var getWish = function() {
    var myWish = wish;
    return myWish;
  };
});
body {
  font-family: "Font Awesome\ 5 Pro";
  font-weight: 900;
}

img {
  width: 50px;
}

.wishlist__list {
  position: absolute;
  right: 0;
}

.wishlist__items li {
  list-style: none;
}
<script src="https://pro.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-id="wishlist">
  <div class="wishlist__list">
    <ul class="wishlist__items">
    </ul>
  </div>
</div>
<div class='products'>
  <div class="items__wish">
    <div id='1' class='item__title item__tile'>Product 1</div>
    <img class="item__img" src="https://www.iconasys.com/wp-content/uploads/2017/06/360-Product-Photography-White-Background-Acrylic-Riser-08.jpg">
    <label class="wish-btn">
    <input type="checkbox" name="wish-check" class='my-wish-add'><i class="wish-icon far fa-heart"></i></input></label>
  </div>
  <div class="items__wish">
    <div id='2' class='item__title item__tile'>Product 2</div>
    <img class="item__img" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoqpSgkG4AQDQOe33jI1NiW3GW2JSB-_v36aREsVyFQH55JFOJ">
    <label class="wish-btn">
    <input type="checkbox" name="wish-check" class='my-wish-add'><i class="wish-icon far fa-heart"></i></input></label>

5
  • Your example code has a TypeError Commented Oct 16, 2018 at 18:11
  • Please reformulate your question. What do you mean by "whether the checkbox is checked from the main item"? Do you mean unchecked? Since checking it = adding it. Commented Oct 16, 2018 at 18:28
  • Yes. So if it is added to the list, you can remove it by both unchecking it from the main item, or the list item. So I guess the main and list item's checkboxes need to be dynamically tied to each other Commented Oct 16, 2018 at 18:32
  • You can add a data-product-id attribute to the items on the remove list, and then change your main .on('change', ...) handler to check whether the checkbox was checked or unchecked, and remove the corresponding item if it's unchecked. Commented Oct 16, 2018 at 18:47
  • Are you able to provide an example snippet? Commented Oct 16, 2018 at 19:22

3 Answers 3

1

if your aim is only to manage wished list by checkboxes this code should be sufficient.

var addedProducts = [];
$(document).on('click', '.items__wish', function() {
    var item = $(this);
    var itemIndex = item.index();
    if (item.parents('.wishlist__items').length > 0) {
        itemIndex = parseInt(item.attr('data-index'))
     }
    if (item.find('.my-wish-add').prop('checked') && addedProducts.indexOf(itemIndex) < 0) {
       if (item.parents('.wishlist__items').length == 0) {
        item.clone().attr('data-index', itemIndex).appendTo($('.wishlist__items'))
        addedProducts.push(itemIndex)
       }
    } 
  else if (item.find('.my-wish-add').prop('checked')==false && addedProducts.indexOf(itemIndex) >= 0) {
 
        $('.products .items__wish').eq(itemIndex).find('.my-wish-add').prop('checked', false);


        $('.wishlist__items .items__wish[data-index="' + itemIndex + '"]').remove(); 
    addedProducts.splice( addedProducts.indexOf(itemIndex), 1 );
 
    }
});
body {
  font-family: "Font Awesome\ 5 Pro";
  font-weight: 900;
}

img {
  width: 50px;
}

.wishlist__list {
  position: absolute;
  right: 0;
}

.wishlist__items li {
  list-style: none;
}
<script src="https://pro.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-id="wishlist">
  <div class="wishlist__list">
    <ul class="wishlist__items">
    </ul>
  </div>
</div>
<div class='products'>
  <div class="items__wish">
    <div id='1' class='item__title item__tile'>Product 1</div>
    <img class="item__img" src="https://www.iconasys.com/wp-content/uploads/2017/06/360-Product-Photography-White-Background-Acrylic-Riser-08.jpg">
    <label class="wish-btn">
    <input type="checkbox" name="wish-check" class='my-wish-add'><i class="wish-icon far fa-heart"></i></input></label>
  </div>
  <div class="items__wish">
    <div id='2' class='item__title item__tile'>Product 2</div>
    <img class="item__img" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoqpSgkG4AQDQOe33jI1NiW3GW2JSB-_v36aREsVyFQH55JFOJ">
    <label class="wish-btn">
    <input type="checkbox" name="wish-check" class='my-wish-add'><i class="wish-icon far fa-heart"></i></input></label>

Sign up to request clarification or add additional context in comments.

Comments

1
+50

Update: You may consider moving removeFromWish() to the same scope as addToWish() so that it is accessible to other functions.

You can use jquery to see if the checkbox is checked, then either append the item or remove the item from the list accordingly.

$(".my-wish-add").on("change", function() {
  var product = getProductValues(this);
  if ($(this).is(":checked")) {
    addToWish({
      id: product.id,
      img: product.img,
      name: product.name,
    });
  } else {
    removeFromWish(product.id);
  }
});

Making these two changes should be able to solve your problem. If you want to uncheck the checkbox upon removal of the list item, you can also try the following:

(function() {
    var currentIndex = i;
    $("#my-wish-remove" + currentIndex).on("change", function() {
      $(this)
        .closest("li")
        .hide(400);
      setTimeout(function() {
        wish.items[currentIndex].stock = "";
        update_product(wish.items[currentIndex]);
        removeFromWish(wish.items[currentIndex].id);
        // uncheck (productID - 1)th checkbox
        $(".my-wish-add").eq(wish.items[currentIndex].id - 1).prop("checked", false);
      }, 400);
    });
  })();

Unchecking a checkbox like this may not be very clear. I hope you get the basic idea and adapt this code so that it fits your style.

[Updated] Demo:

// Wish Function
var wish = {
  items: []
};
var update_product = function(product) {};
$(function() {
  //Add to wish
  var addToWish = function(product, qty) {
    qty = qty || 1;
    var wish = getWish();
    var indexOfId = wish.items.findIndex(x => x.id == product.id);
    if (indexOfId === -1) {
      wish.items.push({
        id: product.id,
        img: product.img,
        name: product.name,
      });
      $parent = $("#" + product.id).closest(".items__wish");
      $parent
        .find(".wish-icon")
        .addClass("active")
        .attr("data-prefix", "fas");
    } else {
      wish.items[indexOfId].qty++;
      wish.items[indexOfId].stock = Number(product.stock);
    }
    //Update popup wish
    updateWish(wish);
  };

  //Remove from wish on id
  var removeFromWish = function(id) {
    var wish = getWish();
    var wishIndex = wish.items.findIndex(x => x.id == id);
    wish.items.splice(wishIndex, 1);
    $parent = $("#" + id).closest(".items__wish");
    $parent
      .find(".wish-icon")
      .first()
      .removeClass("active")
      .attr("data-prefix", "far");
    //Update popup wish
    updateWish(wish);
  };

  var getProductValues = function(element) {
    var productId = $(element)
      .closest(".items__wish")
      .find(".item__tile")
      .attr("id");
    var productImg = $(element)
      .closest(".items__wish")
      .find(".item__img")
      .attr("src");
    var productName = $(element)
      .closest(".items__wish")
      .find(".item__title")
      .html();
    return {
      id: productId,
      img: productImg,
      name: productName,
    };
  };

  $(".my-wish-add").on("change", function() {
    var product = getProductValues(this);
    if ($(this).is(":checked")) {
      addToWish({
        id: product.id,
        img: product.img,
        name: product.name,
      });
    } else {
      removeFromWish(product.id);
    }
  });

  //Update wish html to reflect changes
  var updateWish = function(wish) {
    //Add to shopping wish dropdown
    $(".wishlist__items").html("");
    for (var i = 0; i < wish.items.length; i++) {
      $(".wishlist__items").append(
        "<li>" +
        '<div class="my-wish-item">' +
        "<img src='" +
        wish.items[i].img +
        "' />" +
        '<div class="wish-main">' +
        '<div class="wish-name">' +
        wish.items[i].name +
        "</div>" +
        '<div class="my-wish-remove-container">' +
        '<input type="checkbox" id="my-wish-remove' +
        i +
        '" class="my-wish-remove" aria-hidden="true">' +
        "<i class='fas fa-heart'></i>" +
        "</div>"
      );

      (function() {
        var currentIndex = i;
        $("#my-wish-remove" + currentIndex).on("change", function() {
          $(this)
            .closest("li")
            .hide(400);
          setTimeout(function() {
            wish.items[currentIndex].stock = "";
            update_product(wish.items[currentIndex]);
            $(".my-wish-add").eq(wish.items[currentIndex].id - 1).prop("checked", false);
            removeFromWish(wish.items[currentIndex].id);
          }, 400);
        });
      })();
    }
  };
  //Get Wish
  var getWish = function() {
    var myWish = wish;
    return myWish;
  };
});
body {
  font-family: "Font Awesome\ 5 Pro";
  font-weight: 900;
}

img {
  width: 50px;
}

.wishlist__list {
  position: absolute;
  right: 0;
}

.wishlist__items li {
  list-style: none;
}
<script src="https://pro.fontawesome.com/releases/v5.3.1/js/all.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div data-id="wishlist">
  <div class="wishlist__list">
    <ul class="wishlist__items">
    </ul>
  </div>
</div>
<div class='products'>
  <div class="items__wish">
    <div id='1' class='item__title item__tile'>Product 1</div>
    <img class="item__img" src="https://www.iconasys.com/wp-content/uploads/2017/06/360-Product-Photography-White-Background-Acrylic-Riser-08.jpg">
    <label class="wish-btn">
    <input type="checkbox" name="wish-check" class='my-wish-add'><i class="wish-icon far fa-heart"></i></input></label>
  </div>
  <div class="items__wish">
    <div id='2' class='item__title item__tile'>Product 2</div>
    <img class="item__img" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoqpSgkG4AQDQOe33jI1NiW3GW2JSB-_v36aREsVyFQH55JFOJ">
    <label class="wish-btn">
    <input type="checkbox" name="wish-check" class='my-wish-add'><i class="wish-icon far fa-heart"></i></input></label>

3 Comments

Thanks for this. Where do I re-add the .attr("data-prefix", "far"); to the item itself if it is unchecked? I see it is working if the list item is removed, but if I check and uncheck the main item the icon remains as fas
Based on your code, removing a list item calls removeFromWish(), which re-adds the .attr("data-prefix", "far") to the main item. If you want to re-add this attribute when unchecking the main item, consider moving removeFromWish() to a higher scope, then calling it when the main item is unchecked. Have a look at my updated answer and see if the results are what you expect.
I need the code to change so that instead of removing the items from the list using currentIndex, we match the item with the wishlist item using productId. At site level, using an ordered id like 1, 2, 3 will not work. I changed the id's in the snippet to be unique instead.
0

Here's a much cleaner implementation of the required functionality using buttons. You can just as easily change it to use checkboxes instead.

Pro-tip: While I understand you might have specific requirements, I'd recommend using a component based design approach and considering using pure JavaScript instead of third party libraries like jQuery.

$(function() {
  $("li button").click(function(event) {
    let targetList = '';
    if ($(event.target).closest(".list").attr('id') === 'product-list') {
      targetList = '#wish-list ul';
      targetLabel = 'Remove';
    } else {
      targetList = '#product-list ul';
      targetLabel = 'Add';
    }
    event.target.innerHTML = targetLabel;
    $(event.target).closest("li").appendTo(targetList);
  })
  $("#btn-display-list").click(function() {
    alert(JSON.stringify(getListInfo('#wish-list')));
  })
});

function getListInfo(type) {
  const list = [];
  $(type + " li").each(function(i, target) {
    list.push({
      id: $(target).attr("id"),
      img: $(target).find("img").attr("src"),
      name: $(target).find("h4").html()
    })
  })
  return list;
}
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
  color: #ddd;
  font-weight: lighter;
}

.container {
  display: flex;
}

.list {
  width: 50%;
}

ul {
  padding: 0px;
}

li {
  list-style-type: none;
}

li img,
li div {
  display: inline-block;
  margin-bottom: 10px;
  vertical-align: top;
}

li img {
  max-width: 70px;
}

li h4 {
  margin: 0px;
}

h4,
h3 {
  font-weight: lighter;
}

button {
  background: #0084ff;
  border: none;
  border-radius: 5px;
  padding: 8px 14px;
  font-size: 15px;
  color: #fff;
}

#banner-message.alt {
  background: #0084ff;
  color: #fff;
  margin-top: 40px;
  width: 200px;
}

#banner-message.alt button {
  background: #fff;
  color: #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div id="product-list" class="list">
    <h3>Product Catalog</h3>
    <ul>
      <li id='prod-001'>
        <img class="item__img" src="https://www.iconasys.com/wp-content/uploads/2017/06/360-Product-Photography-White-Background-Acrylic-Riser-08.jpg">
        <div>
          <h4>product 1</h4>
          <button>Add</button>
        </div>
      </li>
      <li id='prod-002'>
        <img class="item__img" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQoqpSgkG4AQDQOe33jI1NiW3GW2JSB-_v36aREsVyFQH55JFOJ">
        <div>
          <h4>product 2</h4>
          <button>Add</button>
        </div>
      </li>
    </ul>
  </div>
  <div id="wish-list" class="list">
    <h3>Wishlist</h3>
    <ul>

    </ul>
  </div>
</div>
<hr/>
<button id="btn-display-list">Show Wishlist</button>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.