Group By feature in AngularJS

Hey there, I'm trying to display a table from the code provided below. The issue I'm facing is with grouping by name. Here's how I want the view to appear:

 Shareholder | Preferred Stock | Common Stock | Options | Percentage |
|-------------+-----------------+--------------+---------+------------|
| Robert      |              35 |           20 |      15 |        54% |
| Bert        |              20 |           20 |      10 |        38% |
| Elizabeth   |              10 |              |         |         8% |
| Total       |              65 |           40 |      25 |       100% |
*/
angular.module('myApp.view2', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view2', {
    templateUrl: 'view2/view2.html',
    controller: 'View2Ctrl'
  });
}])



.controller('View2Ctrl', ['$scope', function($scope) {
    $scope.transactions = [
    { security: 'Preferred Stock',  name: 'Robert',    value: 5,   date: '2014-1-3' },
    { security: 'Preferred Stock',  name: 'Robert',    value: 5,   date: '2014-1-5' },
    { security: 'Common Stock',     name: 'Bert',      value: 20,  date: '2014-1-6' },
    { security: 'Preferred Stock',  name: 'Elizabeth', value: 10,  date: '2014-1-6' },
    { security: 'Common Stock',     name: 'Robert',    value: 20,  date: '2014-1-9' },
    { security: 'Preferred Stock',  name: 'Bert',      value: 20,  date: '2014-1-11' },
    { security: 'Preferred Stock',  name: 'Robert',    value: 5,   date: '2014-1-12' },
    { security: 'Preferred Stock',  name: 'Robert',    value: 15,  date: '2014-1-12' },
    { security: 'Options',          name: 'Bert',      value: 10,  date: '2014-1-13' },
    { security: 'Preferred Stock',  name: 'Robert',    value: 5,   date: '2014-1-14' },
    { security: 'Options',          name: 'Robert',    value: 15,  date: '2014-1-17' }
    ];
}]);

Answer №1

To group items together, you can utilize the reduce function.

angular.module('myApp.view2', [])
  .controller('View2Ctrl', ['$scope', '$filter',
    function($scope, $filter) {

      $scope.securities = ['Preferred Stock', 'Common Stock', 'Options'];

      // Array of transactions
      $scope.transactions = [{
        security: 'Preferred Stock',
        name: 'Robert',
        value: 5,
        date: '2014-1-3'
      }, {
        security: 'Preferred Stock',
        name: 'Robert',
        value: 5,
        date: '2014-1-5'
      },
      ...
      ];

      // Function to add values to a specific group
      function addValue(obj, name, el) {
        var group = obj.securities[name];
        var result = [];
        
        if (!group) {
          obj.securities[name] = group = {name: name};
          result.push(group);
        }

        group[el.security] = (group[el.security] || 0) + el.value;
        group['all'] = (group['all'] || 0) + el.value;

        return result;
      }

      // Function to calculate percentage
      function fixPercent(transactions, total) {
        var totalPercent = 0;
        transactions.forEach(function(el) {
          el.percent = Math.round(100 * el.all / total.all);
          totalPercent += el.percent;
        });

        transactions[transactions.length - 1].percent += 100 - totalPercent;
      }

      // Reduce method to group transactions
      var grouppedTransactions = $scope.transactions.reduce(function(acc, el) {
        acc.total = addValue(acc, 'Total', el)[0] || acc.total;
        acc.result = acc.result.concat(addValue(acc, el.name, el));

        return acc;
      }, {
        securities: {},
        result: [],
        total: {}
      });

      // Display and sort grouped results
      $scope.grouppedTransactions = $filter('orderBy')(grouppedTransactions.result, '-all');
      $scope.total = grouppedTransactions.total;

      // Calculate and adjust percentages
      fixPercent($scope.grouppedTransactions, $scope.total);
    }
  ]);


// CSS style for table formatting
<pre class="snippet-code-css lang-css"><code>table,
td,
th {
  border: 1px solid black;
  border-collapse: collapse;
}
// AngularJS setup script with HTML code for displaying data in a table
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.js"></script>
<div ng-app="myApp.view2" ng-controller="View2Ctrl">
  <table>
    <thead>
      <tr>
        <th>Shareholder</th>
        <th>Preferred Stock</th>
        <th>Common Stock</th>
        <th>Options</th>
        <th>Percentage</th>
      </tr>
    </thead>
    <tbody>
      <tr ng-repeat="sec in grouppedTransactions">
        <td>{{sec.name}}</td>
        <td ng-repeat="secutiry in securities">{{sec[secutiry]}}</td>
        <td>{{sec.percent}}%</td>
      </tr>
    </tbody>
    <tfoot>
      <tr>
        <td>{{total.name}}</td>
        <td ng-repeat="secutiry in securities">{{total[secutiry]}}</td>
        <td>100%</td>
      </tr>
    </tfoot>
  </table>
</div>

Answer №2

While this code snippet may not provide a complete solution, it can serve as a helpful starting point:

let groupedResults = {};
$scope.transactions.forEach(function(transaction) {
  let group;
  if (groupedResults.name) {
    group = groupedResults.name;
  } else {
    group = {name: transaction.name};
    group[name] = group;
  }
  if (group[transaction.security]) {
    group[transaction.security] += transaction.value;
  } else {
    group[transaction.security] = transaction.value;
  }
});

Answer №3

Challenge yourself to calculate the percentage on your own!

var transactions = [
    { security: 'Preferred Stock',  name: 'Robert',    value: 5,   date: '2014-1-3' },
    { security: 'Preferred Stock',  name: 'Robert',    value: 5,   date: '2014-1-5' },
    { security: 'Common Stock',     name: 'Bert',      value: 20,  date: '2014-1-6' },
    { security: 'Preferred Stock',  name: 'Elizabeth', value: 10,  date: '2014-1-6' },
    { security: 'Common Stock',     name: 'Robert',    value: 20,  date: '2014-1-9' },
    { security: 'Preferred Stock',  name: 'Bert',      value: 20,  date: '2014-1-11' },
    { security: 'Preferred Stock',  name: 'Robert',    value: 5,   date: '2014-1-12' },
    { security: 'Preferred Stock',  name: 'Robert',    value: 15,  date: '2014-1-12' },
    { security: 'Options',          name: 'Bert',      value: 10,  date: '2014-1-13' },
    { security: 'Preferred Stock',  name: 'Robert',    value: 5,   date: '2014-1-14' },
    { security: 'Options',          name: 'Robert',    value: 15,  date: '2014-1-17' }
    ];

var summary = [];
var total = {name: 'Total', 'Preferred Stock': 0, 'Common Stock': 0, 'Options': 0};

for(var i = 0; i < transactions.length; i++) {
  var sec = transactions[i].security;
  var val = transactions[i].value;
  total[sec] += val;

  var found = false;
  for(var j = 0; j < summary.length; j++) {
    if(transactions[i].name === summary[j].name) {
      summary[j][sec] += val;
      found = true;
    }
  }

  if(!found) {
    var item = {name: transactions[i].name, 'Preferred Stock': 0, 'Common Stock': 0, 'Options': 0 };
    item[sec] += val;
    summary.push(item);
  }
}

summary.push(total);

console.log(summary);

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 Vue router requires a page reload to see changes and does not have access to the this

When navigating through router-link, the App.vue page opens initially, but the URL changes immediately without displaying the content. Reloading the page is necessary to view it. If you navigate programmatically, you may encounter an error stating 'Ca ...

local individuals and local residents (duplicate) dispatched from the server

Upon analyzing my server's response, I have observed a duplicate of my locals within the locals object. Here is an example: Object { settings: "4.2", env: "development", utils: true, pretty: true, _locals: { settings: ...

Customizing AxiosRequestConfig with Axios in TypeScript can greatly enhance the functionality and

Currently working with React and Axios. Lately, I've been experimenting with custom configurations in Axios as shown below: import $axios from 'helpers/axiosInstance' $axios.get('/customers', { handlerEnabled: false }) However, wh ...

Tips for incorporating nonce or sha into the connect-src directive in Content Security Policy (CSP)

Can a nonce be used in an API request to make sure that the connect-src in CSP doesn't flag it as a malicious address? It appears that nonce can only be used in script-src or style-src, not in connect-src. So far, I have only been able to list URLs ...

Understanding how to monitor a Boolean value that fluctuates in real-time within a three.js

Currently, I am working on developing a 3D 4x4x4 tic tac toe game using three.js. In order to determine the win condition for combinations, I have created a boolean array. With a total of 64 blocks (16*4), I have initialized a boolean array of size 64 with ...

Having trouble with AngularJS ForEach and REST/JSON calls using $resource before the JSON data is ready?

My goal is to iterate through a resource using a controller and output each item in the JSON array with conditionals added later on. However, I am encountering an issue where it returns as "undefined": pfcControllers.controller('pfcArticlesCtrl' ...

Leverage the power of Angular's $http module in conjunction with Django's urlpatterns to fetch

I am attempting to send a $http GET request to a Django URL pattern in order to retrieve a .json file. Is it possible to use urlpatterns to return a file instead of a view? Is this scenario achievable, or are there limitations preventing this from working ...

Retrieve the identification number for each item within my array

I am working with an array of objects, each having a unique ID. My goal is to find the index of each object in the array. I am currently using Angular, however, I am restricted from using $index for this particular task. $scope.getObjectIndex = fun ...

Ways to access dropdown menu without causing header to move using jQuery

Greetings everyone, I am currently working on a dropdown language selection feature for my website. The issue I am facing is that when I click on the language dropdown in the header, it causes the height of the header to shift. $('.language- ...

Retrieve the reference to the plugin object from the element where the plugin is currently active

Take a look at the code below. I've implemented a jquery plugin called myPlugin to modify the UI of #targetElement. var myPluginVar = $('#targetElement').myPlugin(); I have created a button and attached a click event listener to it. $(&ap ...

Is there a simple method to automatically increase the version number of Mongoose documents with each update request?

I'm eager to utilize Mongooses document versioning feature with the "__v" key. Initially, I struggled with incrementing the version value until I learned that adding this.increment() when executing a query is necessary. Is there a method to have this ...

Problem with AngularJS: Button click triggers too quickly on tablet devices, activated by hovering with the mouse

I am encountering an issue with a button inside a div. The problem arises when trying to make the button visible only when the mouse is hovering over the div. While this functionality works smoothly on a PC with a mouse, it behaves differently on a tablet ...

Refreshing the page causes Material UI Button to revert to default styling

My question regarding the Material UI Button losing styling after a page refresh (link: Material UI Button loses Styling after page refresh) went unanswered, so I am reposting with a CodeSandbox included for reference: https://codesandbox.io/s/bold-resonan ...

Retrieving data arrays from response.json

I've been on a wild goose chase trying to solve this puzzling issue. RAWG has transitioned to using their own API instead of Rapid API for game reviews, and I'm in need of data for "Tom Clancy Rainbow Six Siege". Despite my efforts to convert t ...

Unable to locate the <router-view> component within VueRouter

I recently completed a project using Vue.js 3.2.13 and Vue-Router 4.0.14. Despite my efforts to ensure everything was set up correctly, I encountered an error in the browser that said "[Vue warn]: Failed to resolve component: router-view". The specific lin ...

Retrieve Element By Class Name in JavaScript

How can I modify the border color at the bottom of the .arrow_box:after? Javascript Solution document.getElementsByClassName("arrow_box:after")[0].style.borderBottomColor = "blue"; Despite trying this solution, it seems to be ineffective! For a closer ...

The class type "selectLabel" passed to the classes property in index.js:1 for Material-UI is not recognized in the ForwardRef(TablePagination) component

Just started using react and encountering a repetitive error in the console after adding this new component. Here is the full error message: Material-UI: The key selectLabel provided to the classes prop is not implemented in ForwardRef(TablePagination). ...

When using Expressjs MVC, encountering difficulties in retrieving data from mongoose in the listAll() function within the router

I'm currently working on implementing MVC-like architecture in Express.js for a very specific scenario. I suspect there may be an issue with promises, but I'm struggling to debug the problem effectively. Here's how the architecture is set u ...

Refresh the display in $parser

I want to implement a custom validator directive that uses a service to find and validate the input value: app.directive('validator', ['storeService', function (storeService) { return { require: '^ngModel', ...

The switch switches on yet another switch

Greetings everyone, Currently, I am in the midst of my exam project and creating a mobile menu. The functionality is there, but unfortunately, when closing the menu, it also triggers the search toggle which displays an unwanted div, becoming quite botherso ...