Tips for computing values with changing ng-model identifiers

In my angular application, I have a function that creates tables using directives. Each field in the tables must have unique ng-model names so that I can calculate each table individually. To achieve this, I implemented a counter that increments with each added table and appends the current count to the end of each ng-model name for every field (you can refer to my plunkr link for more details).

However, I'm facing an issue with my $scope.total function which sums the fields. It works fine with static ng-model names but I'm struggling to concatenate the ng-model names with the current count to ensure the function calculates each table separately when adding a number after each ng-model. How can I modify my $scope.total function to work with dynamic ng-model names?

Here is my plunkr

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.count = 0;

$scope.total = function(count){
var total = 
// I want to parseFloat the $scope.td1 + the current count.
// How does the syntax look when you concat ng-model.
parseFloat($scope.td1 + count || 0) + 
parseFloat($scope.td2 + count || 0) + 
parseFloat($scope.td3 + count || 0) +  
parseFloat($scope.td4 + count || 0) +  
parseFloat($scope.td5 + count || 0);
return total || 0;
}
});

Edit: I have also added a new input to my plunkr that should display the sum of the "total" in the first two generated tables. However, this functionality is currently not working as expected and I am unable to determine the cause. I introduced a new function to summarize the totals from the first two tables.

Answer №1

To access an object property in JavaScript, you can use either the pointed notation (object.property) or the named array notation (object['property']).

For example, if you have variables set like this:

$scope.td12 = 10;
$scope.td1 = 3;
count = 2;

// This will return 5
$scope.td1 + count;

// This will return $scope.td12 which is equal to 10
$scope['td1'+count];

Answer №2

Revise your total function with the updated code provided below. It should resolve the issue. You can find the revised plunk at this link - http://plnkr.co/edit/vRSQOvRVkUKLZ1ihvBp4?p=preview

$scope.total = function(count){
    // Make sure to parseFloat the $scope.td1 + current count.
    // Double check the syntax for concatenating ng-model values.
    var total = 
    parseFloat($scope["td1" + count] || 0) + 
    parseFloat($scope["td2" + count] || 0) + 
    parseFloat($scope["td3" + count] || 0) +  
    parseFloat($scope["td4" + count] || 0) +  
    parseFloat($scope["td5" + count] || 0);
    return total || 0;
}

Answer №3

An effective strategy is to develop a self-contained table directive that manages its own total and notifies the parent scope when changes occur.

This eliminates the need for confusing counters and cluttering up a single scope with properties for each input.

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  // the totals for each of the tables
  $scope.totals = [];
  $scope.grandTotal = 0;
  // whenever one of the table's total changes, it calls this function
  // with its new total, so we can update our grand total
  $scope.changeTotal = function(index, total) {
    $scope.totals[index] = total;
    $scope.grandTotal = sum($scope.totals);
  }
});

app.directive('myTable', function() {
  return {
    restrict: 'E',
    scope: {
      onTotalChange: '&'
    },
    templateUrl: 'table.html',
    link: function($scope) {
      $scope.values = [];
      // whenever one of the values the inputs are bound to changes,
      // recalculate the total for this table and inform the parent scope
      $scope.$watchCollection('values', function(values) {
        $scope.onTotalChange({
          total: sum(values)
        });
      });
    }
  }
});

// easily sum an array of values in modern browsers
function sum(values) {
  return values.reduce(function(a, b) {
    return a + b
  }, 0);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="plunker" ng-controller="MainCtrl">
  <p>Grand total: {{grandTotal}}</p>
  <!-- Click the button to add a new entry to the totals array
       and display a new table -->
  <button ng-click="totals.push(0)">New table</button>
  <!-- Render a new table for each entry in the totals array.
       Update the total in the array when the table's total changes. -->
  <my-table ng-repeat="i in totals track by $index" on-total-change="changeTotal($index, total)">
  </my-table>

  <!-- Allow the directive to specify a templateUrl of 'table.html' without
     fetching it from the server -->
  <script type="text/ng-template" id="table.html">
    <table>
      <thead>
        <tr>
          <th>head 1</th>
          <th>head 2</th>
          <th>head 3</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>
            <input type="number" ng-model="values[0]">
          </td>
          <td>
            <input type="number" ng-model="values[1]">
          </td>
          <td>
            <input type="number" ng-model="values[2]">
          </td>
        </tr>
        <tr>
          <td>
            <input type="number" ng-model="values[3]">
          </td>
          <td>
            <input type="number" ng-model="values[4]">
          </td>
          <td>
            <input type="number" ng-model="values[5]">
          </td>
        </tr>
      </tbody>
    </table>
  </script>
</div>

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

The lite-server is unable to find an override file named `bs-config.json` or `bs-config.js`

I've been working on running my first Angular 2 app. I carefully followed the steps provided by angular2. However, upon running the command npm start, I encountered the following error in the terminal: No bs-config.json or bs-config.js override fil ...

Using protractor's onPrepare feature to set up for various test suites

In my conf.js file, I have an onPrepare function where I handle logging into the application. This function is executed every time I run one or more test suites, allowing me to log in before running any tests. The problem arises when I do not want to logi ...

Setting up Vagrant with Xvfb Troubleshooting

Setting up a vagrant machine with Ubuntu 14.04 to conduct tests using Selenium and Protractor. The goal is to execute all tests on this headless machine without the need for a graphical interface, just plain terminal output. Following these resources for ...

Engaging with the crossrider sidepanel extension

When it comes to the crossrider sidepanel, I prefer using an iframe over js-injected html to avoid interference with the rest of the page. However, I am struggling to establish any interaction between my browser extension and the iframe. I believe adding ...

Tips for creating an SVG element on a plane using THREE.js

I am attempting to duplicate an existing svg element within a THREE.js environment. Following this example, I convert the svg to an image, create a plane with a texture based on the image, and then add it to the scene. However, I am encountering an issue ...

The redesigned pie chart animations in d3 are experiencing glitches

Previously, I had a pie chart with fantastic animations. You can view it here: https://jsfiddle.net/tk5xog0g/29/ I tried to rebuild the chart and improve it based on my needs, but the animations no longer work as intended. I suspect this might be due to ...

Struggling to make image uploading function with Flask and JQuery

Utilize the code snippet below to submit forms and retrieve a modified version of text from Flask using AJAX and JQuery: from flask import Flask, render_template, request, jsonify app = Flask(__name__) @app.route('/') def index(): return re ...

Bootstrap: when divs cover the jumbotron

I have recently started exploring bootstrap and have been using it to build a homepage for my website. However, I am facing an issue: The three images are overlapping the jumbotron section and I can't seem to figure out why. Below is the HTML code sn ...

What is the best way to send props and trigger a function with a single onclick event?

Is there a way to receive a prop and activate a function using the same onclick event? In the navbar.js file, the props are passed like this: <Hamburger menuOpen={this.ToggleMenu} /> In the Hamburger.js file, the props are received. Currently, the ...

Trouble arises when implementing AJAX in conjunction with PHP!

I am facing an issue with my PHP page which collects mp3 links from downloads.nl. The results are converted to XML and display correctly. However, the problem arises when trying to access this XML data using ajax. Both the files are on the same domain, b ...

Arranging xCharts based on the weekday order

Struggling with xCharts, specifically trying to display a bar chart showing numbers with corresponding days of the week in order. Despite my efforts, I can't seem to get them to appear in the correct sequence. Refer to the image below for reference: ...

AngularJS: A guide to clicking with the mouse and using the Enter key on the ng-grid

Working with ng-grid in angular and I'm wondering how I can successfully select a row by clicking with the mouse and then pressing Enter. Currently, pressing Enter changes the selected row, which is not the desired behavior. I'm looking to have ...

When transitioning between different node.js apps, the URL localhost:3000 remains constant

As I was launching a fresh node.js application (referred to as app 2), an unexpected and puzzling phenomenon occurred. I decided to run app 2 after spending some time working on another application earlier in the day (app 1). With the previous app, there w ...

Collapse in Bootstrap 3 Navigation Bar

I'm really struggling to understand why my navbar is refusing to collapse. I've included the necessary Bootstrap CSS and JS files, as well as the transition and collapse JS files. Below is the code that I've been working with. Any assistance ...

Using ReactJS to capture keydown events from an iframe

I am trying to implement keydown event handling for an iframe within a ReactJS component. The iframe contains an embedded video, and I want to be able to capture keyboard events while the video is playing. Can someone please assist me with how to achieve ...

Show the information stored in an array using Angular

I have recently transitioned from using React to learning Angular, and now I am facing the challenge of displaying data from an array. My goal is to implement a dropdown menu where users can select an ID and see the corresponding address displayed. I bel ...

IE displays unresolved list instead of content in AngularJs multiple select

I'm currently utilizing AngularJS to bind a list of employees into a multi-select tag. Here's the snippet of code I've been working with: <select class="form-control" ng-model="event.attendees" ng-options="c.Email as c.FullName f ...

What is the best way to determine the total number of rows that have been generated by the Asp:Repeater?

I'm looking for a way to retrieve the total number of rows generated by the repeater control using either Javascript or JQuery. Can anyone help me with this? ...

"Exploring the process of making Ajax calls to a specific URL using a

Hello there! I'm currently working on a project where I need to retrieve data without refreshing the page. Below is my ajax code: function fetchData() { $.ajax({ type: "post", cache: false, url: "test2.php", success: (function (resu ...

Experiencing issues with receiving null values in formData when using React hooks

Hello everyone, I am currently experiencing some challenges while utilizing React functional components hooks with formData. The issue I'm facing is that I am receiving null data in formData even though I am using useState hooks. Instead of getting th ...