Column Classes

Column Classes

oneillgoneillg Posts: 33Questions: 9Answers: 0

Hi,

I am able to set classes for columns successfully in DataTables using things like:
'columnDefs': [
{
className: 'dt-center',
targets: [0,1,2]
}]

Since I use the DataTables everywhere I pass this in to my 'implementTable' routine as an object -- that also works. I have also discovered that I can have more than one class (i.e. className: 'dt-center font-larger')

However what I really want to do is to have one class for two columns and another for the others. I also need to pass that in as an object.

Here is how I pass one of them:

var cellClassesObj = new Array();
var cellClassObj = new Object();
cellClassObj.className = 'btnTop';
cellClassObj.targets = [0];
cellClassesObj.push(cellClassObj);
tableObj.cellClassesObj = cellClassesObj;
implementTable(tableObj);

The problem happens when I push more than one cellClassObj onto the array. Is there another way to do it?

Thanks,

-Gabe

Answers

  • kthorngrenkthorngren Posts: 20,309Questions: 26Answers: 4,770
    edited January 2018

    Sounds like you are doing something like this - reusing the same object with different values:

    var cellClassesObj = new Array();
    var cellClassObj = new Object();
    cellClassObj.className = 'btnTop';
    cellClassObj.targets = [0];
    cellClassesObj.push(cellClassObj);
    
    cellClassObj.className = 'dt-center';
    cellClassObj.targets = [1];
    cellClassesObj.push(cellClassObj);
    

    If so then you will end up with something like this:

    The first push cellClassesObj looks like this:

    [
    {className: "btnTop", targets: [0]},
    ]
    

    the second it will look like this:

    [
    {className: "dt-center", targets: [1]},
    {className: "dt-center", targets: [1]}
    ]
    

    The array will have pointers that reference the object cellClassObj, not the actual object. When you change the values for cellClassObj its still the same object that the pointers refer to.

    You can use console.log to see this.

    You can try this to clone the object:
    cellClassesObj.push(Object.assign({}, cellClassObj));

    For more info please see this:
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

    Or you could simply do this:

    cellClassesObj.push({className: "btnTop", targets: [0]});
    cellClassesObj.push({className: "dt-center", targets: [1]});
    

    Kevin

  • oneillgoneillg Posts: 33Questions: 9Answers: 0

    Thanks Kevin,

    Yes I did see a mistake re I did not instantiate a second object. Here is my corrected version:

    var cellClassesObj = new Array();
    var cellClassObj = new Object();
    cellClassObj.className = 'dt-center';
    cellClassObj.targets = [1];
    cellClassesObj.push(cellClassObj);
    
    cellClassObj = new Object();
    cellClassObj.className = 'coloredRed';
    cellClassObj.targets = [0,1];
    cellClassesObj.push(cellClassObj);
    
    tableObj.cellClassItems = cellClassesObj;
    implementTable(tableObj);
    

    However it still does not work

    inside of implementTable:

    var cellClasses = tableObj.cellClassesObj ? tableObj.cellClassesObj : "";
    . . . 
    
           'columnDefs': [
                {
                    "targets": cellTarget,
                    "createdCell" : createdCell,
                    "render": colRender
                },
                cellClasses
            ],
    
  • oneillgoneillg Posts: 33Questions: 9Answers: 0

    Actually the code in my last message was wrong inside of implementTable. Should be:

    var cellClasses = tableObj.cellClassItems ? tableObj.cellClassItems : "";
    . . .

    Still does not work.

  • kthorngrenkthorngren Posts: 20,309Questions: 26Answers: 4,770
    edited January 2018

    I see... the problem is cellClasses is an array resulting in something like this:

           'columnDefs': [
                {
                    "targets": cellTarget,
                    "createdCell" : createdCell,
                    "render": colRender
                },
                [
                {className: "dt-center", targets: [1]},
                {className: "coloredRed", targets: [0, 1]}
                ]
            ],
    

    An array within an array which is not a supported config. If you did this it would work:
    columnDefs: cellClasses,

    I'm not sure of a clean way to combine cellClasses with the columnDefs you have configured. Maybe someone with more JS experience can help.

    Kevin

  • oneillgoneillg Posts: 33Questions: 9Answers: 0

    I guess the question is does the DataTables object itself support more than one 'set' of classes and targets.

  • kthorngrenkthorngren Posts: 20,309Questions: 26Answers: 4,770

    It seems like the first className for a column is the one applied. The second is not Try this example based on your code:
    http://live.datatables.net/cacinadu/1/edit

         {className: "dt-center", targets: [1]},
         {className: "coloredRed", targets: [0, 1]}
    

    Column 0 is red while column 1 is black and centered. But if you change to this:

         {className: "dt-center coloredRed", targets: [1]},
         {className: "coloredRed", targets: [0, 1]}
    

    Column 0 is red and column 1 is red and centered. Based on this test I would say that you will need to build your classes by columns. @allan may provide more details or corrections to my assumptions.

    Kevin

  • oneillgoneillg Posts: 33Questions: 9Answers: 0

    I did detect that the following does indeed work:

            'columnDefs': [
                {
                    "targets": cellTarget,
                    "createdCell" : createdCell,
                    "render": colRender
                },
                {
                     className: 'dt-center',
                     targets: [1]
                },
                {
                    className: 'coloredRed',
                    targets: [0,1,2],
                }
    
            ],
    

    Now all I have to do is somehow transfer my multidimensional array into something that looks like the above.

  • oneillgoneillg Posts: 33Questions: 9Answers: 0

    To get yours to do what you were trying, try this: (it works). So it looks like we're close except how do I combine it with my existing columndefs?

    var cellClassesObj = new Array();
    var cellClassObj = new Object();
    cellClassObj.className = 'dt-center ';
    cellClassObj.targets = [1];
    cellClassesObj.push(cellClassObj);

    cellClassObj = new Object();
    cellClassObj.className = 'dt-center coloredRed';
    cellClassObj.targets = [0,1];
    cellClassesObj.push(cellClassObj);

  • kthorngrenkthorngren Posts: 20,309Questions: 26Answers: 4,770

    Doesn't work for me:
    http://live.datatables.net/raledujo/1/edit

    Column 1 is centered but not red.

    The concat() method is what I think you need. Please see the same example.

    Kevin

  • oneillgoneillg Posts: 33Questions: 9Answers: 0

    Actually I got everything to work. Thank you Kevin for helping me to work it out.

    Look at this: http://live.datatables.net/cidimaco/1/edit

    The key is in this instance I want different classes for different columns. You'll see in the example I have one red and the other centered. Again, you can add more classes with spaces if you wanted the classes to overlap.In other words I could have done this in the second one:

    cellClassObj = new Object();
    cellClassObj.className = 'dt-center coloredRed';
    cellClassObj.targets = [0];
    cellClassesObj.push(cellClassObj);

    In my real code I had to merge with other variables being used. So I just added the existing ones on to my other object and now everything is working great.

    var columnDefsObj = tableObj.cellClassesObj;
    

    // this is other stuff I was already using
    var newCDObj = new Object();
    newCDObj.targets = cellTarget;
    newCDObj.render = colRender;
    newCDObj.createdCell = createdCell;

    columnDefsObj.push(newCDObj);
    

    then later all I needed was:

    'columnDefs': columnDefsObj,
    

    Thanks again for your work. It really helped me!!

  • oneillgoneillg Posts: 33Questions: 9Answers: 0

    Actually you were right about the concat. It gets tricky when you combine the objects and arrays.

    Final working code inside implementTable:

    var columnDefsObj = new Array();
    // this can be a multidimensional array of classes applied to different columns.
    if (tableObj.cellClassesObj){
        columnDefsObj = columnDefsObj.concat(tableObj.cellClassesObj);
    }
    
    
    var newColDefObj = new Object();
    newColDefObj.targets = cellTarget;
    newColDefObj.render = colRender;
    newColDefObj.createdCell = createdCell;
    columnDefsObj.push(newColDefObj);
    
This discussion has been closed.