Problem with showing values in a Javascript table

2

I have the following code that generates a table from some data that comes from an array, the code shows me the values of each product per week and its total in the following way:

-----------------------------------------------------
Land     |     Product   |    25   |    26   | Total |
-----------------------------------------------------
FINCA1   |     ROSA      |   2000  |   1254  |  3254 |
-----------------------------------------------------
FINCA2   |     ROSA      |   1900  |   123   |  2023 |
-----------------------------------------------------
FINCA3   |     ROSA      |   350   |   200   |  550  |
-----------------------------------------------------
FINCA3   |     ROSA1     |   410   |    0    |  410  |
-----------------------------------------------------
TOTAL    |               |   4660  |   1577  |  6237 |
------------------------------------------------------


var data = [
  {id:1, land: 'FINCA1',  product: "ROSA", week:25,  quantity: 2000}, 
  {id:1, land: 'FINCA2',  product: "ROSA", week:25, quantity: 1900}, 
  {id:1, land: 'FINCA3',  product: "ROSA", week:25, quantity: 350},
  {id:1, land: 'FINCA3',  product: "ROSA1",week:25, quantity: 410},
  {id:1, land: 'FINCA1',  product: "ROSA", week:26, quantity: 1254},
  {id:1, land: 'FINCA2' ,  product: "ROSA",week:26, quantity: 123},
  {id:1, land: 'FINCA3' ,  product: "ROSA",week:26, quantity: 200}
];

//Obtengo los keys del objeto para crear el Thead de la tabla y los guardo en una variable

var tabla = document.createElement('table');
var tableHead = document.createElement('tr');

Object.keys(data[0]).forEach(prop=>{
  if(prop != 'week' && prop != 'quantity')
  tableHead.innerHTML += '<th>'+prop+'</th>';
});

var semanas = data.reduce( (semanas_, elemento)=>{
  if(semanas_.indexOf(elemento.week) == -1)
    semanas_.push(elemento.week)
  return semanas_;
}, []);

semanas.forEach( semana=>{
  tableHead.innerHTML += '<th>'+semana+'</th>';
});


var total_semanas = [];


tableHead.innerHTML += '<th>Total</th>';
tabla.appendChild(tableHead);

var tbody = document.createElement('tbody');

tabla.appendChild(tbody);

document.querySelector('body').appendChild(tabla);

var arrayOrganizado = data.reduce((arr, item)=>{


  var t = total_semanas.find(e=> e.semana === item.week);
  if (t) t.total += item.quantity;
  else total_semanas.push({ semana : item.week, total : item.quantity });


  item.week = {
    numero : item.week,
    cantidad : item.quantity
  }
  var ele = arr.find(it=>it.land === item.land && it.product === item.product);
  if(ele){
    ele.week.push(item.week);
    ele.total = ele.week.reduce((a, b)=> a + b.cantidad, 0);
  } else {
    item.week = [item.week];
    item.total = item.quantity;
    arr.push(item);
  }
  return arr;
}, []);

arrayOrganizado.forEach(fila=>{
  var f = Object.keys(fila).reduce( (a, b)=>{
    //console.log(b);
    if(b != 'week' && b != 'quantity' && b != 'total')
      return a +  '<td>' + fila[b] + '</td>';
    return a;
  }, '');
  tbody.innerHTML += f + semanas.reduce( (a, _, i)=>a + '<td>' + (fila.week[i] ? fila.week[i].cantidad : 0) + '</td>', '') + '<td>' + fila.total + '</td>';   
});

var f = Object.keys(arrayOrganizado[0]).reduce( (a, b)=>{
  //console.log(b);
  if(b != 'week' && b != 'quantity' && b != 'total')
    return a +  '<td> ---- </td>';
  return a;
}, '');

tbody.innerHTML += f + total_semanas.reduce( (a, _, i)=>a + '<td>' + _.total + '</td>', '') + '<td>' + total_semanas.reduce( (a, b) => a.total + b.total) + '</td>'; 

So far everything is fine, the problem is that when you increase the weeks, there may be weeks that do not have values and the result is 0, but instead of putting that value in the corresponding week, you put it in the last one, I explain:

The arrangement can arrive as follows

var data = [
      {id:1, land: 'FINCA1',  product: "ROSA", week:25,  quantity: 2000}, 
      {id:1, land: 'FINCA2',  product: "ROSA", week:25, quantity: 1900}, 
      {id:1, land: 'FINCA3',  product: "ROSA", week:25, quantity: 350},
      {id:1, land: 'FINCA3',  product: "ROSA1",week:25, quantity: 410},
      {id:1, land: 'FINCA1',  product: "ROSA", week:26, quantity: 1254},
      {id:1, land: 'FINCA2' , product: "ROSA", week:26, quantity: 123},
      {id:1, land: 'FINCA3' , product: "ROSA", week:26, quantity: 200},
      {id:1, land: 'FINCA3' , product: "ROSA", week:24, quantity: 200}
      {id:1, land: 'FINCA3' , product: "ROSA", week:23, quantity: 1200}
    ];

The table should look like this:

-----------------------------------------------------------------------
Land     |     Product   |    23   |    24   |   25  |  26  |   Total |
-----------------------------------------------------------------------
FINCA1   |     ROSA      |   0     |   0     |  2000 | 1254 |  3254   |
-----------------------------------------------------------------------
FINCA2   |     ROSA      |   0     |   0     |  1900 | 123  |  2023   | 
-----------------------------------------------------------------------
FINCA3   |     ROSA      |   1200  |   200   |  350  | 200  |  1950   |
-----------------------------------------------------------------------
FINCA3   |     ROSA1     |   0     |    0    |  410  |   0  |  410    |
-----------------------------------------------------------------------
TOTAL    |               |   1200  |   200   |  4660 | 1577 |  7637   |
-----------------------------------------------------------------------

However, the table looks like this;

-----------------------------------------------------------------------
Land     |     Product   |    23   |    24   |   25  |  26  |   Total |
-----------------------------------------------------------------------
FINCA1   |     ROSA      |   2000  |  1254   |  0    | 0    |  3254   |
-----------------------------------------------------------------------
FINCA2   |     ROSA      |   1900  |   123   |  0    | 0    |  2023   | 
-----------------------------------------------------------------------
FINCA3   |     ROSA      |   1200  |   200   |  350  | 200  |  1950   |
-----------------------------------------------------------------------
FINCA3   |     ROSA1     |   410   |    0    |    0  |   0  |  410    |
-----------------------------------------------------------------------
TOTAL    |               |   1200  |   200   |  4660 | 1577 |  7637   |
-----------------------------------------------------------------------

I think it's the function that reduces the problem in this part:

tbody.innerHTML += f + semanas.reduce( (a, _, i)=>a + '<td>' + (fila.week[i] ? fila.week[i].cantidad : 0) + '</td>', '') + '<td>' + fila.total + '</td>';

I do not know if there is another similiar function that does the same, or I do not know if it is that function, I appreciate your help

    
asked by Fabian Sierra 23.07.2016 в 16:09
source

1 answer

1

The problem is not in the reduced function but in the ordering of the data and the inclusion of the missing data. I did not investigate much in the code nor do I intend to make improvements, I only solved the errors that generated that the data will be shown in the incorrect columns.

  • The data is not ordered: if you want to show the number of the week in order, it is always necessary to order them at some point. In the example you have, the weeks are arranged as follows:

    25 | 26 | 24 | 23

  • The weeks are in the same order in which they are presented in the array called data . so you can apply sort in the weeks array so that at least the header is fine.

    var semanas = data.reduce( (semanas_, elemento)=>{
      if(semanas_.indexOf(elemento.week) == -1)
        semanas_.push(elemento.week)
      semanas_.sort();
      return semanas_;
    }, []);
    
  • The information in each row is incorrectly indexed, for example if in total there are 7 weeks, but each file has 2, 3 or 4 weeks, in the form in which it was being indexed the information will always be shown in the first ones columns of the row and the others will be filled with zeros. There are many ways to do it, one can be insert in each row values that represent the missing weeks, I chose at the time of showing each cell, check if that week exists for the current row, if there is to show the value, put zero if not.
  • The difference between the two methods depends more on the expected performance, but for most of the cases there are no big penalties at runtime.

    tbody.innerHTML += f + semanas.reduce( function(a, c, i){
            var w = fila.week.find(function(current,index,fila_weeks){
            return current.numero===c;
                });
              if (w===undefined){
                w=0;
              }else{
                w=w.cantidad;
              }
            return a + '<td>' + w + '</td>'},   '') + '<td>' + fila.total + '</td>';   
    });
    

    Edit: sorting is added to the row of totals.

    You can try the full code in this jsfiddle .

        
    answered by 23.07.2016 / 19:43
    source