Tips on setting a value to zero in Angular when there is no input

Is there a way to organize the data and show the PRN entries based on the date, for instance, when the month is January? If there is data for machine 1 with assetCode: PRN, it should be displayed under the header for children. Similarly, if there is data for machine 2 with assetCode: PRN1, it should be added under the children for the month of January. If there is no data for machine 1 with assetCode: PRN1, it should be set to 0, the same goes for machine 2 as well.

Below is the provided code snippet:

list.component.ts

rowData = [
{
      code: "Machine 1",
      assetCode: "PRN",
      assetCount: 1,
      date: "2019-01-18 00:00:00"
    },
    {
      code: "Machine 1",
      assetCode: "PRN",
      assetCount: 1,
      date: "2019-01-19 00:00:00"
    },
    {
      code: "Machine 2",
      assetCode: "PRN 1",
      assetCount: 3,
      date: "2019-01-20 00:00:00"
    },
    {
      code: "Machine 3",
      assetCode: "PRN",
      assetCount: 1,
      date: "2019-01-21 00:00:00"
    },
    {
      code: "Machine 4",
      assetCode: "PRN 1",
      assetCount: 3,
      date: "2019-01-22 00:00:00"
    },
    {
      code: "Machine 5",
      assetCode: "PRN 1",
      assetCount: 3,
      date: "2019-01-23 00:00:00"
    }
];
this.columnDefs.push(
      {
        'headerName': 'Style/Machine',
        'field': 'code',
        'pinned': 'left',
        'lockPosition': true
      }
    );

    for (let i = 0; i < 12; i++) {

      const record = {
        'headerName': this.monthNames[i].monthName,
        'children': [
          {
            'headerName': 'Total',
            'columnGroupShow': 'closed',
            'field': 'total'
          }
        ]
      };

record.children.push(
          {
            'headerName': 'PRN',
            'columnGroupShow': 'open',
            'field': 'assetCount'
          }
);
this.columnDefs.push(record);
}

How can I achieve a similar layout as shown in the image below?

https://i.sstatic.net/8oKvq.jpg

Answer №1

Upon reviewing the code and data provided for the issue at hand, it appears that they are not completely compatible and adjustments are needed to achieve the desired grid layout.

The code utilizes 'Column Groups' for display structuring, while the grid headers 'PRN,...,PRNX' are closely tied to the attributes 'assetCode' and 'assetCount' in the data object. Therefore, the recommended approach would be to implement ag-grid 'Pivoting' to address this issue.

Pivoting involves converting column values into separate columns.

  1. Firstly, the structure for all 'Machines X' rows needs to be defined:
{
  code: "Machine X",
  PRN:  1,
  PRN1: 5,
  PRN2: 7,
  ...
  PRNX: XX,
  month: "January"
},{
  code: "Machine X",
  PRN:  1,
  PRN1: 3,
  ...
  PRNX: XX,
  month: "February"
},

  1. The next step involves configuring columns for which totals should be calculated (PRN headers will be created during data transformation later on):
var gridOptions = {
    ...
    //Enabled 'Pivot' feature
    pivotMode: true, 
    //Headers won't include aggFunc, e.g., 'sum(PRN)'
    suppressAggFuncInHeader: true,
    //Additional properties for group display
    autoGroupColumnDef: {
        headerName: "Style/Machine", 
        field: "code", 
        width: 200,
        cellRendererParams:{
          suppressCount: true,
        },
    },
    //Customize display & ordering of pivot headers
    processSecondaryColGroupDef: function(colGroupDef) {
      var res = colGroupDef.headerName.split("_");
      var month = monthNames[res[0]];
      colGroupDef.headerName = month+'\''+res[1];
    },
    columnDefs: columnDefs,
    rowData: null
};

Main header for groupings:

{ headerName: "Code",  field: "code", rowGroup: true}

To pivot rows based on the 'month' column, set 'pivot: true':

 { headerName: "Month", field: "month", pivot: true},
  1. In the subsequent step, transform the input data to align with the structure from Step 1:
//Group data per month/year for each 'Machine X'
var dataByMonthYear = rowData.reduce(function(dataByMonthYear, datum){
  var date  = new Date(datum.date);
  var year  = ('' + date.getFullYear()).slice(-2);
  
  var index = datum.code+'_'+date.getMonth() + '_' + year;
  
  if(!dataByMonthYear[index]){
     dataByMonthYear[index] = {code: datum.code, month: date.getMonth() + '_' + year};
  }
  if(!dataByMonthYear[index][datum.assetCode]){
     dataByMonthYear[index][datum.assetCode] = 0;
  }

  dataByMonthYear[index][datum.assetCode] += datum.assetCount;

  if(columns.indexOf(datum.assetCode) === -1){
     columns.push(datum.assetCode);
  }

  return dataByMonthYear;
}, {});

var finalRowData = Object.keys(dataByMonthYear).map(function(group){
  return dataByMonthYear[group];
});
  1. Finally, define the columns:
{ 
    headerName: "PRN", field: "PRN", 
    aggFunc: customAggFunction
},

And the custom aggregate function for counting & column definition:

function customAggFunction(values) {
   var sum = 0;
   values.forEach( function(value) {
        if (typeof value === 'number') {
            sum += value;
        }
    });
    return sum;
}

columns.map(function(col){
  columnDefs.push({ headerName: col, field: col, aggFunc: customAggFunction
     });
});

An alternative solution would involve using full groups instead of pivoting, but it would require defining multiple columns for each YEAR_MONTH_PRN, which might be heavier in terms of performance for large datasets with multiple PRNs over several years.

View Working Example

Additional comments:

"If in month of March there's PRN 1 it will display, but if there's no PRN in the month of March it should display."

The second solution, focusing on pivot columns and dynamic column handling based on total values, would be more suitable for displaying the required information effectively. This approach ensures flexibility in showing/hiding columns based on the specific period's data total.

Please note that the second solution, while effective, may not be the most optimized due to the need for double data processing to map all columns and assign values. If possible, obtaining a list of periods ('assetCode/month/year') from the server side could streamline the process.

View Working Example v2

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

Tips for updating information within a vue-component

I am working on a Vue component where I retrieve data from localStorage. Here is how I handle it: if (localStorage.getItem("user") !== null) { const obj_user = localStorage.getItem('user'); var user = JSON.parse(obj_user); } else { ...

"Enable real-time editing with inline save/submit feature in

I'm struggling to figure out how to extract the modified content from a CKEditor instance and send it to a URL. I've been referencing something like this: but I can't seem to determine how to save the changes. Is there a way to post the up ...

Remove any javascript code from the ajax modal when it is closed or hidden

I am in the process of creating a music website that showcases songs along with their lyrics. One of the features I have added is a lyrics button that, when clicked while a song is playing, opens up a modal displaying the live lyrics. Everything works per ...

Connecting data from a .ts file in one webpage to the HTML content of another webpage

I am currently working on implementing the binding concept in Angular. The code snippet below is from PageOne.ts: this.navCtrl.push("PageTwo",{ paramType: params, }) Here is a snippet from PageTwo.html: <span>{{paramType}}</span> ...

Issue encountered while attempting to send a POST request from a React application to the Rocket backend

When attempting to send a POST request from my single page application, I encounter a 404 error, even though the route functions properly in Postman. routes.rs #[post("/letters", format = "application/json", data = "<new_letter>")] fn write_letter( ...

Messages and responses from an array within a discord.js bot

Currently, I am attempting to set up my discord.js version 12.0.0 bot to react to specific words using arrays for words and corresponding responses. However, I am encountering the following error message: TypeError: Cannot read property 'split' o ...

Assign the filename to the corresponding label upon file upload

I've customized my file uploader input field by hiding it and using a styled label as the clickable element for uploading files. You can check out the implementation on this jsFiddle. To update the label text with the actual filename once a file is s ...

I have an Observable but I need to convert it into a String

Seeking assistance with Angular translation service and Kendo.UI components. In the Kendo.UI documentation, it mentions the use of MessageService for component translation implementation. To achieve this, an abstract class must be extended containing a m ...

Acquiring the URL from the ajax response with EmberJS

Seeking assistance on extracting the URL from an Ajax response within Ember. This is necessary for handling a particular scenario where the server redirects to a different URL and provides data from the new URL (302 redirect). By capturing the URL from th ...

Angular 14: Removing elements from FormArray causes the remaining elements to lose their values

My form includes custom inputs and utilizes the ControlValueAccessor. To view the implementation, visit this link. I encountered an issue where deleting an item from a FormArray would inadvertently clear the values of the other FormGroups still present in ...

Typescript - Troubleshooting undefined error with static variables

My node API app is developed using express and typescript. The static variable of the Configuration Class is initialized with required configuration before starting the server. However, when I try to use this static variable in a separate TypeScript class ...

Retrieving multiple lines of text from the database and populating a TextArea

I am encountering an issue with multi line text saved in a MySql database as VARCHAR 255. When I retrieve and process it using the nl2br PHP function, it displays correctly (with multiple lines). However, when I retrieve the multi line text from the databa ...

How to properly fill state values for testing components with React Testing Library?

Introducing my custom component -> export default() => { const [list, setList] = useState([]) const handleAddToList = () => { // Executes an API call and updates the list state. setList(response); } return ( <div> ...

return to the original secured page based on the most recent language preference

I'm facing an issue with a logical redirection that needs to redirect users to the previous protected page after login. The login functionality is implemented using my custom login page and Google Credentials. Additionally, I have set up a multilingu ...

The Angular application is showing "&#40" instead of "("

When I make an HTTP request and receive JSON data, I encounter a problem when displaying it in my HTML using curly braces {{}}. Certain characters like "(" appear as "&#40". Is there a way to convert these special characters back to their normal form? ...

What is causing my auth0 token to expire upon refreshing the page or clicking a link in my Angular application?

I've implemented authentication in my Angular single-page application using auth0. I followed a tutorial on their website: https://auth0.com/docs/quickstart/spa/angular2 After completing the login tutorial, everything seemed to be working fine. impo ...

"Encountering issue with jQuery $.ajax DELETE not triggering then() function

I have implemented some code within a Chrome extension that effectively utilizes the then() method from the xhr response when using $.ajax. if (request && request.action === "updateTask") { $.ajax({ type: "PUT", url: config.upda ...

Using TypeScript, effortlessly retrieve objects within React components based on their keys

I am looking for a way to dynamically choose a React component based on a key within an object import React, {useState, useEffect} from 'react' import ComponentA from '@components/ComponentA'; import ComponentB from '@components/Co ...

Exploring Passportjs Callbacks and parsing arguments

I'm struggling to grasp the concept behind the custom callback in Passport.js. I'm not sure why it requires (req, res, next) at the end. Shouldn't these values be obtained from closure? app.get('/login', function(req, res, next) { ...

State mutation not reflected in input field value update

During the development of a small project for educational purposes, I encountered an issue with updating the input value. Below is the simplified component causing this issue. function TipSelector({selections, onTipChanged}: {selections: TipSelectorItem[], ...