0

Is it possible to define the cell color with a nested property of the object mapped to the table ?

The JSON structure of the objects is :

objects: [
{
  "agent": "agent_1",
  "days": {
     day_0: {
       "code": "ABC",
       "color": "#0062cc"
     },
     day_1: {
       "code": "DEF",
       "color": "#a09494b2"
     }
  },
  {
  [...]
  }
]

I have a table defined like this :

let columns = [
  {title: "Agent", dataKey: "agent"},
  {title: "january 1st", dataKey: "day_0"},
  {title: "january 2nd", dataKey: "day_1"}]

let rows = [
  {agent: "agent_1", day_0: "ABC", day_1: "DEF"},
  [...]
]

All that works fine. But I'd like to set the color of each day cell dynamically, set with the color code of the corresponding object. Something like :

createdCell: function(cell, data) {
  {
     cell.styles.fillColor = "day_0.color";
  }
}

But I can't figure how to pass the data to the table. Is it possible ? Can displayProperty help in any way ?

  • Yes that would work, although you would have to set an actual color instead of ""day_0.color", like [255, 0, 0] for red. – Simon Bengtsson Aug 10 '18 at 09:34
  • Thanks @Simon Bengtsson for the answer. I got that, it would be `cell.styles.fillColor = "#0062cc";`. But the problem is that the color may be different for each cell. So how could I dynamically set it with the corresponding attribute ? – Manuel De Zutter Aug 10 '18 at 09:44
  • Something like this? `if (typeof cell.raw === 'number') { cell.styles.fillColor = [255, 0, 0] }`. I think I'm missing something can you elaborate? – Simon Bengtsson Aug 10 '18 at 11:57
  • Each cell in the table corresponds to a "day" object. One of the attributes of the object is a color code (like "#a09494b2" for example) which corresponds to the color to apply to the cell. But from one pdf to another, the days printed will be different, and so will be the color to apply to each cell. So I can't put in the code a direct value like "[255, 0, 0]", as it may change. I need to indicate the value of the attribute. Is it clearer now ? – Manuel De Zutter Aug 10 '18 at 12:43
  • Aha, so what you are asking about is how to convert a hex color to rgb values? https://stackoverflow.com/questions/5623838/rgb-to-hex-and-hex-to-rgb Could b used something like this: `cell.styles.fillColor = hexToRgb(cell.raw)` – Simon Bengtsson Aug 10 '18 at 13:13
  • No, that's not the question (though your answer might help later!). The point is how to set the color value of a cell, not hard-coding it, but instead by passing an attribute value. Thanks for taking the time to try to understand my problem :-) – Manuel De Zutter Aug 10 '18 at 13:34

2 Answers2

2

EDIT: In this case it was that v2.3.4 of jspdf-autotable was needed

Based on our comments discussion I think I understood your problem. You can try something like this (with the hexToRgb function from here)

let columns = [{
    title: "Agent",
    dataKey: "agent"
  },
  {
    title: "january 1st",
    dataKey: "day_0"
  },
  {
    title: "january 2nd",
    dataKey: "day_1"
  }
]

let objects = [{
  agent: "agent_1",
  day_0: {
    "code": "ABC",
    "color": "#00ff00"
  },
  day_1: {
    "code": "DEF",
    "color": "#ff0000"
  }
  // etc
}];

let doc = jsPDF()
doc.autoTable(columns, objects, {
  createdCell: function(cell, data) {
    let hex = cell.raw.color
    if (hex) {
      let rgb = hexToRgb(hex)
      cell.styles.fillColor = rgb;
      cell.text = cell.raw.code
    }
  }
});
doc.save('jhg.pdf')

function hexToRgb(hex) {
    var bigint = parseInt(hex.replace('#', ''), 16);
    var r = (bigint >> 16) & 255;
    var g = (bigint >> 8) & 255;
    var b = bigint & 255;
    return [r, g, b];
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.4.1/jspdf.debug.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/2.3.4/jspdf.plugin.autotable.js"></script>
Simon Bengtsson
  • 7,573
  • 3
  • 58
  • 87
  • The agent prints fine, but in the day cells, I get "[object Object]" printed instead of the code ("ABC"). And the color don't print either. I tried with the code only, but with the same result. Is it because the day is a nested object with two attributes ? – Manuel De Zutter Aug 10 '18 at 15:57
  • Strange, it works for me. Added the hexToRgb above so you can run it now. – Simon Bengtsson Aug 10 '18 at 16:28
  • After many tests, I still can't make it work. The code snippet works when I run it here, I copied it exactly in my code, but I still have the [object Object]. The HextToRgb method works as well when I run it separately. It seems it doesn't recognize the cell.raw.color and cell.raw.text. Maybe it comes from the structure of the project. I'm using typescript and angular 6. Would it be the reason? – Manuel De Zutter Aug 13 '18 at 08:35
  • Hmm, shouldn't be. Which versions of the jspdf and which version of jspdf-autotable are you using? – Simon Bengtsson Aug 13 '18 at 09:27
  • jspdf : 1.4.1 jspdf-autoTable: 3.0.0-alpha.3 – Manuel De Zutter Aug 13 '18 at 10:00
  • 1
    It worked when I switched to version 2.3.4 of jspdf-autotable. Thanks a lot for your help Simon! :-) – Manuel De Zutter Aug 13 '18 at 12:16
0

I just leave the answer here just in case anyone needs it.

We can use the didParseCell hook.

doc.autoTable({
      head: [[..., color]],
      body: [[..., #ffffff], [..., #ff0000]], // pass hexa value to the cell
      didParseCell: function (HookData) { 
        if (HookData.cell == undefined) 
          return; 
        // find cell taht contains the hexa value
        // the change the fillColor property
        // and set the cell value to empty
        var color = HookData.cell.text[0];
        if (color.match(/^#[a-fA-F0-9]{3}([a-fA-F0-9]{3})/g) != null) { 
          HookData.cell.styles.fillColor = hexToRgb(color);
          HookData.cell.text = [];
        }
      }
    });

Code to convert hexa to RGB:

hexToRgb(hex) {
    var bigint = parseInt(hex.replace('#', ''), 16);
    var r = (bigint >> 16) & 255;
    var g = (bigint >> 8) & 255;
    var b = bigint & 255;
    return [r, g, b];
  }

Package version:

jspdf : 2.5.1

jspdf-autotable :3.5.25

Quyết
  • 502
  • 5
  • 12