Avoid duplicate items from being added to an array in AngularJS

I have created an Angular Single Page Application that includes a cart feature where users can add items. My goal is to prevent users from adding the same item to the cart more than once.

function CartForm($scope) {

  $scope.products = [{
    "description": "BB-8 Droid",
    "qty": "1",
    "cost": "99"
  }, {
    "description": "C-3PO Droid",
    "qty": "1",
    "cost": "499"
  }, {
    "description": "R2-D2 Astromech Droid",
    "qty": "1",
    "cost": "899"
  }, {
    "description": "R5-D4 Astromech Droid",
    "qty": "1",
    "cost": "899"
  }, {
    "description": "IG-88 Bounty Hunter Droid",
    "qty": "1",
    "cost": "899"
  }];
  $scope.invoice = {
    items: []
  };

  $scope.addItem = function(product) {
      $scope.invoice.items.push(product);
    },

    $scope.removeItem = function(index) {
      $scope.invoice.items.splice(index, 1);
    },

    $scope.total = function() {
      var total = 0;
      angular.forEach($scope.invoice.items, function(item) {
        total += item.qty * item.cost;
      })

      return total;
    }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<h2>Shopping Cart Example</h2>
<div ng:controller="CartForm">
  <table class="table">
    <thead>
      <th>Description</th>
      <th>Qty</th>
      <th colspan="2">Price</th>
    </thead>
    <tr ng-repeat="product in products">
      <td>{{product.description}}</td>
      <td>{{product.qty}}</td>
      <td>{{product.cost | currency }}</td>
      <td>
        <button class="btn btn-danger" ng-click="addItem(product)">ADD TO CART</button>
    </tr>
  </table>
  <table class="table">
    <tr>

      <th>Description</th>
      <th>Qty</th>
      <th>Cost</th>
      <th>Total</th>
      <th></th>
    </tr>
    <tr ng:repeat="item in invoice.items">
      <td>
        <input type="text" ng:model="item.description" class="input-small">
      </td>
      <td>
        <input type="number" ng:model="item.qty" ng:required class="input-mini">
      </td>
      <td>
        <input type="number" ng:model="item.cost" ng:required class="input-mini">
      </td>
      <td>{{item.qty * item.cost | currency}}</td>
      <td>
        [<a href ng:click="removeItem($index)">X</a>]
      </td>
    </tr>
    <tr>
      <td></td>
      <td></td>
      <td>Total:</td>
      <td>{{total() | currency}}</td>
    </tr>
  </table>
</div>

Check out the live JSFiddle demo here: http://jsfiddle.net/tedleeatlanta/22591h2y/15/

Answer №1

If you want to streamline your AddItem function, you can implement some logic to handle all of the scenarios.

While it may not be the most elegant solution, the following approach will point you in the right direction:

    $scope.addItem = function(product) {
            var exists = false;
            for(var index = 0; index < $scope.invoice.items.length; index++){
                if ($scope.invoice.items[index].description == product.description)
                {
// Using parseInt here because the Qty isn't a number
                    $scope.invoice.items[index].qty  = parseInt($scope.invoice.items[index].qty) + 1;
                    exists = true;
                }
            }
            if (!exists)
                $scope.invoice.items.push(product);
        },

This code snippet updates the quantity if the item already exists, or adds it to the list if it does not.

You can test this implementation by running it at this link: http://jsfiddle.net/22591h2y/16/

Alternatively, if you prefer to avoid using parseInt, consider changing the qty property of your objects from strings to integers. Check out the modified version at: http://jsfiddle.net/22591h2y/17/

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Steps to trigger a dialog to appear automatically within an Icon Menu with React Material UI

In my application, I have an icon menu implemented along with an array that contains the possible values for the items in the menu. Here is an example of how the array looks: listItems = { [ { label: 'ZERO', t ...

References to high order functions in JavaScript

Although the code below is functional, I believe there might be a more efficient approach. I am currently passing a reference to the higher-order function's scope. var self=this; this.nodeModal.find(".modal-footer .save").click(function(){ ...

What is the best way to fill an array within an object using React Hooks?

I am encountering an issue with an object that includes an array. Here is the code snippet in question: const [data, setData] = useState({ jobs: [] }); Currently, I am retrieving data from an API and need to append this fetched information to the jobs arr ...

Can you create a stroke that is consistently the same width as the container BoxElement?

Utilizing a BoxElement provided by the blessed library, I am showcasing chat history. New sentences are inserted using pushLine. To enhance readability, days are separated by lines (which are added using pushLine). The width of each line matches that of t ...

Inserting a value into a Node/Express session

I am currently immersed in a project that involves Node, Express, and MongoDB. Mongoose is the tool I use to shape my schemas and interact with the database. In addition, I utilize the "express-sessions" module where a session value named "req.session.user ...

Display logo when website has been scrolled

On my website, I want to display a logo in the header only when the site has been scrolled. I attempted to accomplish this with JavaScript: if(document.getElementById("div").scrollTop != 0){ document.write("<img src='logo.jpg'>"); } How ...

Updating databases with the click of a checkbox

Currently, I am developing a program for monitoring cars as part of my thesis. My current focus is on user management, and I have come across an issue where the database needs to be updated when the status of a checkbox changes. To visualize checkboxes, y ...

Trouble arises when attempting to establish an isolated scope within Angular alongside UI Bootstrap

My table of data is set up with AngularJS, and one of the columns is calculated using a function in the controller. On my webpage, I have a button that opens a modal. When I use UI Bootstrap to open the modal, it creates a new isolated scope (child of the ...

Is it possible to drag the div container in HTML to resize its width from both left to right and right to left?

After posing my initial inquiry, I have devised a resizing function that allows for the expansion of a div's width. When pulling the right edge of the div to resize its width from left to right, is it possible to adjust the direction or how to resize ...

Retrieve the URL for the React component

I'm facing some challenges with React fundamentals :/ I have a piece of code that creates a table using JSON data: import React from 'react' import { DataTable } from 'react-data-components'; function createTable(data) { ...

What is the best way to extract URLs with varying numbers of slashes in angular.js?

My goal is to create an Angular website focused on managing files, allowing users to navigate through a file system tree similar to how it's done on Github (example: github.com/angular/angular.js/tree/master/path/to/my/file.js. I want to extract the ...

What steps are involved in uploading data to serve as a filter while running a PHP script to retrieve data from an SQL database?

Currently, I am retrieving data from a PHP file using miniAjax. The code snippet below demonstrates how the process begins: microAjax("genjsonphp.php", function(data) { var json = JSON.parse(data); var points = json; //code continues In the c ...

Vue js lacks the ability to effectively link HTML elements to corresponding JavaScript functions

I seem to be missing a crucial element in my spring boot application. I am attempting to follow the initial steps outlined in the Vue documentation to create the most basic Vue application possible. Here is what I currently have: @Controller public class ...

What is the method for displaying script commands within package.json files?

With a multitude of repositories, each one unique in its setup, I find myself constantly referencing the package.json file to double-check the scripts. "scripts": { "start": "npm run dev" "build:dev": "N ...

Tips on implementing .on() with querySelector in jquery?

Can you help me convert the jQuery code below into a querySelector method? <script type="text/javascript"> jQuery(function($){ $('#woocommerce-product-data').on('woocommerce_variations_loaded', function() { $ ...

Issues with React Router functionality on a live production site are causing complications

I recently created an Amazon-clone UI using create-react-app, but it only displays dummy data. The issue arises after deploying it to Vercel - the routing does not function as expected. When clicking on links, a blank page appears with correct URL paramete ...

The form I created retrieves select options via an ajax call, but after saving, the post values are not displaying as expected

I have created a form with the following HTML code snippet: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Populate City Dropdown Using jQuery Ajax</title> <script type="text/javascript" src="h ...

What is the best way to dynamically link an Angular Material table with information pulled from the backend server

I am attempting to connect a mat-table with data from the backend API following this Angular Material Table Dynamic Columns without model. Below is the relevant content from the .ts file: technologyList = []; listTechnology = function () { ...

ThymeLeaf does not support the parsing of JavaScript code

I'm working on serving an Angular app with spring boot/thymeleaf. This is the structure of my class that sends html/css/javascript: @Controller public class ResourceProvider { @RequestMapping(method = RequestMethod.GET, value = "/") ...

Creating MySQL query results in Node.js manufacturing process

I am looking to format the MySQL result in Node.js in a specific way. The desired result format should look like this: [ { "m_idx" :1 , "contents" : { "m_name" : "a", ...