handy
handy

Reputation: 1076

Adding column to datatables

im using Zend and Datatables (jQuery Plugin). I have a table like that:

<table width="100%" cellpadding="0" cellspacing="0" border="0" class="display" id="customerTable">
    <thead>
        <tr>
            <th><?php $this->trans('ID') ?></th>
            <th><?php $this->trans('Name') ?></th>
            <th><?php $this->trans('Comment') ?></th>
            <th><?php $this->trans('Options') ?></th>
        </tr>
    </thead>
    <tbody>

    </tbody>
    <tfoot>
        <tr>
            <th><?php $this->trans('ID') ?></th>
            <th><?php $this->trans('Name') ?></th>
            <th><?php $this->trans('Comment') ?></th>
            <th><?php $this->trans('Options') ?></th>
        </tr>
    </tfoot>
</table>

I'm creating my array like that:

public function jsonAction() {
    $this->_helper->layout->disableLayout();
    $albums = new Application_Model_DbTable_Customers();
    $albums = $albums->fetchAll()->toArray();

    foreach($albums as $entry) {
        $x[] = array($entry['id'], $entry['name'], $entry['comment'], '');
    }
    $this->view->json = json_encode(array("aaData" => $x));
}

As you see, im creating an array which i encode to json afterwards. For the Options field, i just added ''.

In the Options field, i want some edit icons etc. How can i get to that easily? Somehow, this solution doesn't seem to be as nice as it could be.

I'm thinking of something like, predefined my table without the option fields. So my JSON matches it. Then, do something like:

$('#myTable').datatables({
    'optionsColumn' : {path/to/icon.jpg, /url/it/calls,
                       second icon etc}
}); 

Or just something like addColumn(HTML) which gets repeated for every entry. I don't want to put HTML into my action, and adding it afterwards via JS sucks also.

Thanks

Upvotes: 2

Views: 3511

Answers (3)

Greg Pettit
Greg Pettit

Reputation: 10830

There are a bunch of ways to do this. Here's one. Now, for the sample code it might be important to note that my data is coming into "aaData" as a 3D object as opposed to a 2D array. I don't know for sure that mDataProp or even aoColumns is available to 2D data.

2D (not what I am using):

['column1', 'column2', 'column3'], ['moreColumn1', 'moreColumn2', 'moreColumn3] &hellip; etc &hellip;

3D (this is what I am using):

[{'key1': 'column1', 'key2': 'column2', 'key3': 'column3'}, {'key1': 'moreColumn1', &hellip; etc &hellip;}]

To add a column with a widget, you just need to be using aoColumns, and create an entry with an mDataProp of null. You can add a class to it (as a hook for a JavaScript function) and add any other default content (such as one or more edit icons, text, or whatever):

"aoColumns": [
    {
      "mDataProp": null,
      "bSortable": false,
      "sClass": "editControl",
      "sDefaultContent": '<span class="editIcon"></span>'
    },
    {
      "mDataProp": "key1"
    },
    {
      "mDataProp": "key2"
    },
    {
      "mDataProp": "key3"
    }
]

In this example, the icon is added as the background image of a span class (CSS not shown). There are other ways to accomplish the goal, and I agree with an earlier poster that you may want to just send a "placeholder" column. This will definitely work with a 2D array. If you are going to use a placeholder column, you're treading into the "mixing concerns" territory, but if it's blank then it might be a worthwhile tradeoff.

If that's the way you go, I would add the images, etc. in the fnRowCallback.

"fnRowCallback": function( nRow, aData ) {

      // let's imagine we are sending a URL in one of the columns and we want it to
      // be stored in a clickable first column.

      var theLink = aData[1];

      $('td:eq(0)', nRow).addClass('clickable editIcon').attr('href', theLink);

      return nRow;
    }

Again, the icon itself would be created as a background-image, in this case for the TD element. You could use .html() and add whatever markup you want, though, enabling you to use image elements instead. It's just an example... not all browsers support href as a property of a td. But hopefully it gives the right idea as a starting point.

Upvotes: 3

bpeterson76
bpeterson76

Reputation: 12870

I use DataTables extensively in my apps, and I also do the icons for actions quite often. My chosen method to attack this issue is to include them in the array foreach as a properly escaped string, then output the mess as JSON to Datatables in the manner you're showing. Often, the first couple of times it won't work, and it will either fail silently or with a "coded" error like "aData null" or "sEcho unknown." The first thing you have to do is output the JSON somehow (my chosen method is to email) and then run it through jsonlint.com 99 times out of 100, your images will be improperly escaped.

It certainly is possible to append to existing data using fnUpdate, but it'll be an evgen slower process.

I would encourage you to think far ahead on this task. I did all my tables initially using the DataTables DOM method, then quickly moved to JSON as you're doing when my users started complaining of slow load times. As we've grown and users started adding a ton more data than I expected, this method got too slow, so we had to switch to server-side DataTables transactions. If you expect to be handling more than 1000 records at a time, I'd suggest going with the server side solution rather than going this route.

Upvotes: 0

Flater
Flater

Reputation: 13773

I've tried something similar a few days ago, but I noticed DataTables doesn't like you editing the DOM of the table after it has been initialised. But if your tags are already in place, you can add things to the td-elements without issue.

So I would suggest creating dummy column(s). You can hide them after DataTables has been initialized (haven't tested it, but I would assume hiding them before initialising will also work).

Upvotes: 0

Related Questions