2

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

1
  • Any chance you could post your JSON output? That would make it possible for us to debug. Commented Dec 12, 2011 at 16:06

3 Answers 3

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks. You actually just told me that, what i was thinking before i went looking for the answers. :) With you help and the docs, i got it solved. Here is my solution: pastebin.com/LGF1NqD3 My table is like: ID, Name, Comment, Options. My Json just got the Data for ID, Name and Comment. Thats why i use sDefaultContent. It sets all fields which are null to ''. After that im adding the html to the option fields. Just made edit yet, as you see. Thanks!
I even shortened it. pastebin.com/PYJxBUnK Just use fnRender, specify your content and then via fnTarget say, to which it should get applied.
Excellent! I have to admit I rarely think of fnRender since I'm running stuff through fnRowCallback already. I'll have to keep it in mind. :-)
0

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).

2 Comments

Dummy columns aren't going to help if you can't get the image links in the table in the first place. They'll fail whether they're hidden or not....
Correct me if I'm wrong (please do :)) but no issue of loading images specifically is mentioned? I am able to insert content into my table fields witout issue, but inserting a new part to the structure of the table itself brings along more issues. I would really just hold off the inserting part until after the table has been initialised (or before it, and then you can change the table structure as well). But changing the structure afterwards tends to either fail or not do what you want it to do.
0

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.

3 Comments

The newer bDeferRender would have helped at the stage before moving to server-side. :-) You also don't need to output your icons as part of the JSON; this will unite your visual and data concerns, which isn't an ideal scenario. You can keep the two separate! I'll see if I can whip up an answer to demonstrate.
bDeferRender aside, JSON in datatables can't handle much more than 1000-ish lines without affecting the user experience with long load times. When one of my clients unexpectedly added 1M records to their database, it was time to redo my datatables with server-side. I agree it's important for people to know alternatives, but you're kidding yourself if you think DataTables is efficient working with mass quantities of records in the DOM. You have to pare it down (and hopefully pipeline) to be efficient.
Absolutely agree. ANY data-intensive application should have its data processed on the server side, not in the DOM. With 1000 lines, DT and bDeferRender will still work but I wouldn't personally do it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.