Fill a table using ng-repeat and verify that the header data matches

In my project, I have an array of years that are used to populate the table header row. Additionally, there is an object containing data that populates the table itself. The challenge is to place the correct year data under the corresponding year header. This requires checking if the year(Y) in the object matches the year in the header array, and adding an empty cell if they don't match. The object is sorted by year. What would be the most effective approach to achieve this? You can view the code on JSFiddle.

CONTROLLER

 var app = angular.module("testModule", []);
 app.controller('testController', function($scope) {
 $scope.headerYears = [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020];

$scope.rows = [{
  "Name": "Name1",
  "Col": [{
    "Y": 2013,
    "M": 25711
  }, {
    "Y": 2014,
    "M": 26095
  }, {
    "Y": 2015,
    "M": 23641
  }, {
    "Y": 2016,
    "M": 22224
  }, {
    "Y": 2017,
    "M": 21968
  }, {
    "Y": 2018,
    "M": 23820
  }, {
    "Y": 2019,
    "M": 26673
  }, {
    "Y": 2020,
    "M": 29329.5
  }]
}, {
  "Name": "Name2",
  "Col": [{
    "Y": 2013,
    "M": 83
  }, {
    "Y": 2014,
    "M": 461
  }, {
    "Y": 2015,
    "M": 1067
  }, {
    "Y": 2016,
    "M": 1120
  }, {
    "Y": 2017,
    "M": 1050
  }, {
    "Y": 2018,
    "M": 600
  }, {
    "Y": 2019,
    "M": 475
  }, {
    "Y": 2020,
    "M": 481
  }]
}, {
  "Name": "Name3",
  "Col": [{
    "Y": 2013,
    "M": 25794
  }, {
    "Y": 2014,
    "M": 26556
  }, {
    "Y": 2015,
    "M": 24708
  }, {
    "Y": 2016,
    "M": 23424
  }, {
    "Y": 2017,
    "M": 23297
  }, {
    "Y": 2018,
    "M": 24412.5
  }, {
    "Y": 2019,
    "M": 27090.5
  }, {
    "Y": 2020,
    "M": 29754.5
  }]
 }]
});

HTML

<table border="1" data-ng-app="testModule" data-ng-controller="testController">
   <thead>
    <tr>
      <th ng-repeat="i in headerYears">{{i}}</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="row in rows">
      <td ng-repeat="item in row.Col">{{item.M}}{{item.Y}}</td>
    </tr>
  </tbody>

Answer №1

To conditionally show elements in the DOM, I would use ng-if.

<table border="1" data-ng-app="testModule" data-ng-controller="testController">
  <thead>
    <tr>
      <th ng-repeat="i in headerYears">{{i}}</th>
    </tr>
  </thead>
  <tbody>
    <tr >
      <td ng-repeat="i in headerYears" >{{i}}  
      <span ng-repeat="row in rows"></span> 
      <span ng-repeat="item in row.Col">{{item.Y}} </span>
      </td>     
    </tr>
  </tbody>
</table>

Additionally, you can include an NG-IF directive within the span elements like this: span ng-if="item.Y==i" and another span ng-if="item.Y != i"

Answer №2

To ensure consistency in the columns of your table, it is important to consider that the length of row.col can vary compared to the length of headerYears.

For each row, you must iterate over headerYears to maintain uniform column sizes throughout.

Refer to this example I have created, which might provide a solution for you.

It is advisable to create a new array of objects linked to the years specified in the controller and then use ng-repeat on this new array.

In my opinion, this approach will result in a cleaner DOM structure that is easier to manage.

I have included a filter to parse through column data and display the appropriate information based on each situation.

 app.filter('testFilter', function() {
    return function(col, header) {
       if (!col ){
        return "Empty";
       } 
       if (!header){
        return "Empty"; 
       }


       var returnVal="Empty Item";
       angular.forEach(col, function(colItem){
         if(header===colItem.Y) {
            returnVal = colItem.M+" "+colItem.Y;
        }
       });

    return returnVal;

   }
});

The DOM structure has also been updated to resemble the following:

<tbody>
   <tr ng-repeat="row in rows">
      <td ng-repeat="i in headerYears">
         {{row.Col | testFilter:i }}
      </td>
   </tr>
</tbody>

Answer №3

This method is much more efficient than creating a custom filter for each value you want to display. By using {{item.myProperty}} within the TD, you can insert any HTML you desire. Enjoy!

It organizes your data to align with the headers, allowing JavaScript to perform optimally and providing clean data to Angular. I hope this explanation is helpful!

//BEGINNING OF FUNCTIONAL CODE
$scope.rows = null;

(function(){
  var raw = [{ /** all existing "rows" data has been transferred here**/ }];

  var bucketize = function(col) {
      var data = new Array();
      for (var i = 0; i < $scope.headerYears.length; i++) {
          data.push({}); //initializing structure based on headerYears
          for (var j = 0; j < col.length; j++) {
              if (col[j].Y == $scope.headerYears[i]) {
                  data[i] = col[j]; //replacing dummy value with actual data
              }
          }
      }
      return data;
  };

  var rows = new Array();

  for (var x = 0; x < raw.length; x++) {
    var row = raw[x];
    row.Col = bucketize(row.Col); //sorting and formatting data for intended HTML        
    rows.push(row);
  }

  $scope.rows = rows; //providing cleansed data to Angular
})();
//END OF FUNCTIONAL CODE

--UPDATE--

An infinite digest loop occurs because a new Array() is returned every time the bucketize() function is called. To avoid this, scrub the data before passing it to Angular (refer to the above section). This can be done in an AJAX success handler or within a SEAF function like demonstrated earlier.

//CAUTION: AVOID INFINITE LOOP BY ELIMINATING "new Array();"
...
<td ng-repeat="item in bucketize(row.Col)">{{item.Y}}</td>
...
$scope.bucketize = function(col) {
    var data = new Array();
    for (var i = 0; i < $scope.headerYears.length; i++) {
        data.push({}); //initializing structure based on headerYears
        for (var j = 0; j < col.length; j++) {
            if (col[j].Y == $scope.headerYears[i]) {
                data[i] = col[j]; //replacing dummy value with real data
            }
        }
    }
    return data;
};
//END OF AVOIDABLE CODE
  • Kieron

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

A div element springs forth into a new window and seamlessly transitions back to its original position with fresh content

Most of us are familiar with Gmail chat, where you can pop out the chat window into a new window with its content, and then pop it back in to its original position. However, I encountered an issue while working on replicating this functionality. While I w ...

In order of service - avoid repeating the initial service upon the next user click if the second service was unsuccessful

Seeking assistance. I am new to Angular + RxJS, so please bear with me if this task seems easy. The concept is to submit a form that includes multiple input fields, one of which is for uploading an image. When the user clicks the submit button, the first ...

Issue with displaying Images on Datatables using Javascript

I have been scouring the depths of the Internet. Everything was running smoothly, I was handling image uploads and retrievals with NodeJs to MongoDB using the schema below: image: { data: fs.readFileSync(path.join(__dirname, '/public/uploads/&apos ...

Getting JSON data from an Angular JS controller can be achieved by utilizing the built-in

My user login function includes a method called logincheck, which takes in parameters and sends a request to the server. Upon success, it redirects the user to the dashboard with the member ID. this.logincheck = function(log) { var pa ...

guide for interpreting a complex json structure

I'm attempting to extract data from a JSON file that has multiple layers, like the example below. - "petOwner": { "name":"John", "age":31, "pets":[ { "animal":"dog", "name":"Fido" }, ...

To navigate to a personalized HTML page from a different custom creation

Imagine I have created 3 web pages: fake google, fake facebook, and fake instagram. Currently, I am on the fake google page, and I want to navigate to either fake facebook or fake instagram based on what I type into the search box. How can I achieve this r ...

Google App Engine does not properly interpret PHP code when making AJAX requests

I am currently facing an issue with using AJAX request on Google App Engine. In my local development environment, everything works fine and the request is correctly interpreted. However, when I deploy the code to production, the AJAX request renders the co ...

Having trouble with material-ui installation in React, Redux, and React-Router project

Guide: https://i.stack.imgur.com/k1UMV.png Due to using redux and react router, incorporating MuiThemeProvider at the top of the chain is a bit challenging. What would be the most effective method to integrate this particular library? This is my ReactDO ...

If the URL Element is Present in the IMG SRC

Is there a way to write jQuery code that will check if the 'page.php' is present in the src attribute of an image? And if it is, then skip running the 'example function' on that image. But if 'page.php' is not found in the img ...

Ways to retrieve various JSON arrays in Javascript

I have a Java servlet that constructs JSON objects and arrays and sends them as a response. After sending the initial JSON data, I then loop through a list to create more JSON objects. JSONObject jsonObject = new JSONObject(); JSONArray jsonArray = new JS ...

Is there a way to access the filtered or organized rows in the Quasar Q-Table?

I have encountered a roadblock in my project. Despite installing Quasar version 2.0.0, I realized that it lacks a property to access the filtered or sorted rows. Previous versions of q-table had a computedRows property which was missing in the latest ver ...

Implement the LinkedIn API within an AngularJS application

I am a beginner in both Angular and JavaScript, and I am attempting to incorporate the LinkedIn API into my AngularJS project in order to automatically populate certain forms with data from LinkedIn. I have already tested it by including everything in the ...

Is it possible to generate a unique name from an array without any repeats?

Update: I am not looking to create a single list, but rather a button that generates a random name when clicked. Objective: Generate a random name from an array by clicking a button. The goal is to display one name at a time randomly without repetition. W ...

What is the method for invoking an Angular controller function with a parameter value that has been freshly displayed on the current view?

After simplifying my code for better understanding, I am facing an issue with a mean.js application. The backend is organized with express and mongodb, and all resource endpoints are functioning properly independently. However, the problem arises when deal ...

React - Paths of images converting to relative when directly accessed via the address bar

Whenever I click on a route link, everything works perfectly. The images have the correct path in the DOM and load successfully. However, if I manually type the URL into the address bar with the route suffix included, like example.com/services, the image ...

jQuery: changing the order of list elements with the eq method

I've been tackling a challenge with designing a navigation bar that consists of 3 items. The goal is to have the clicked item move to the center position on the horizontal navbar while re-arranging the order. Here's the code snippet I've com ...

Decoding the file's encoding: A beginner's guide

I need help determining the encoding of a file in order to only upload CSV files with utf-8 format. If there are any non utf-8 characters, I want to display an error message. Currently, I am utilizing Papa Parser for parsing. Is there a way to detect the ...

Exploring the potential of VSCode's RegEx search and replace

I am working on an Angular translation file and need to perform a search and replace operation in VScode for the translate key. The goal is to extract only the final key and use it in the replacement. The keys are structured with a maximum depth of 3 level ...

Stopping the parent from triggering jQuery

I am currently working on enabling the folding and unfolding of a nested list by clicking either the li element or the adjacent input type=[checkbox]. However, when checking the checkbox, it triggers the parent li to fold along with the container li. You ...

Deleting a key from one object will also remove that key from another object - JavaScript

I have come across an interesting issue with my Javascript code. I am working with two objects, dict1 and dict2, where I need to maintain a form of state and then post the final object. When I click on certain buttons, I assign dict1 to dict2. However, wh ...