2

Updated with correct UI code - custom rendering using orthogonal data

I'm working with MVC C# within framework 4.5.1 and I'm having an issue creating custom sorting within a table utilizing jquery datatables 1.10.7. Bootstrap is used within the project too.

Everything was working as expected initially, but that changed when I decided to custom render a column to display an image. The image is rendering just fine, but sorting doesn't work at all for this new column. The JSON being returned as the datasource for this column is an object with 3 properties: Process.Id, Process.Description, and Process.ImageUrl. The sorting should work based on the Process.Id. The render just creates an image tag, and there's some logic in there to dynamically add some information to the title. The last render creates a button link to view more details.

Here's the datatable initialization in my view, which is called during doc ready:

UPDATE: columnDefs has been updated to render correctly when I need the custom sort value, or the image tag.

function LoadDataTable() {
    table = $('#accountsRequests').DataTable(
      {
          "destroy": true,
          "processing": true,
          "ajax":
              {
                  "type": "GET",
                  "url": "@Url.Action(MyActionName, MyControllerName)"
              }
          , "paging": true
          , "columns": [
                { "data": "UserId" },
                { "data": "Process", title: "Status" },
                { "data": "LastName", "title": "Last Name" },                 
                { "data": "UserId" }
          ]
          , "columnDefs": [
              {
                  "targets": 0, // hiding first column, userId
                  "visible": false,
                  "searchable": false,
                  "sortable": false
              },
                 {
                     "targets": 1,
                     "render": function (data, type, row) {
                         var element = "<img id='status_" + row["UserId"] + "' src='" + data["ImageUrl"] + "' data-order='" + data["Id"] + "' data-sort='" + data["Id"] + "'  title='" + data["Description"] + "";

                           if (type === "sort" || type === 'type') {
                                 return data["Id"];
                             }
                             else {
                                 if (data["Id"] == "2") // add in-process name
                                 {
                                     var userId = row["ProcessUserId"].trim();
                                     element = element + " by " + userId;
                                 }
                                 return element + "'/>";
                             }                         },
                     "searchable": false,
                     "sortable": true
                 },                            
              {
                  "targets": 3,
                  "render": function (data, type, row) {
                      return "<a class='btn btn-default' role='button' href=\"@Url.Action(MyOtherAction, MyController)?userId=" + row["UserId"] + "\">View Details</a>"
                  },
                  "searchable": false,
                  "sortable": false
              }
          ]           
      });
}

And this is what it looks like on the UI:

enter image description here

Here's the Process object definition:

enter image description here

I have attempted to dynamically add the data-sort and data-order HTML5 attributes into my render statement, but that doesn't seem to do anything. This adds these attributes to the image itself, which might not be valid for sorting.

I've also attempted to use the createCell callback function, shown below and that doesn't work at all, regardless what I put in there. In my example, as a quick test, I'm attempting to add something to ALL cells. And I get nothing.

"createdCell": function (cell, cellData, rowData, rowIndex, colIndex) {
              $(cell).attr('data-userId', 'adsfadsasfas');} 

Just to make sure that this is working as expected I inserted a createRow function just to make sure. I've worked with this before so I knew what it should look like when working. Works. Boooyah!

 "createdRow": function (row, data, index) {
              $(row).attr('data-userId', 'fadsafasdfdasfasfasa');           }

Here's the output showing that the createdRow function is working, but nothing for the createdCell.

enter image description here

So, what am I doing wrong, and how can I add the sorting property that I want (the Process.Id), regardless of what's actually displayed? Can I add a sort property to the Column definition? I've seen something similar but I'm not sure. Any help is appreciated! Please let me know if there's any clarification needed in the above explanations.

5
  • 1
    Take a look at orthogonal data Commented Jul 21, 2016 at 20:44
  • I added the orthogonal data to the columns definition, but I still can't sort on a the field. When I remove the rendering and just display the Id value, all sorts just fine (and would probably work just fine without the orthogonal data). I'm still missing something, and I've updated the above question to illustrate my changes. Please take a look and see my changes. Commented Jul 22, 2016 at 16:12
  • 1
    If you take a look at the documentation, the _: and sort: are supposed to go in the render: option, not the data: option. Try that and see if anything changes. Commented Jul 22, 2016 at 16:29
  • All the examples I've found either have the render within the column (not in the DATA as you've said) or the columnDefs configuration. When in the column config, I've only found examples that use a single data source. When in the columnDefs, I've only seen the function where you're returning custom output. Neither, as far as I can get to work, returns BOTH parts that I need (custom sort and custom output). What am I missing? Commented Jul 22, 2016 at 17:57
  • First of all, columnDefs and columns are essentially the same thing; anything you can define in columnDefs can also be defined in column. One issue (and the reason I'm commenting instead of answering) is that I've never tried to use render as a function with orthogonal data, so I don't know if it is exactly the same syntax. If it helps, try moving all your columnDefs stuff into the columns declaration. See the documentation for these here and here. Commented Jul 22, 2016 at 18:00

1 Answer 1

1

The issue that I was missing is the fact that the RENDER function (whether in Column or ColumnDefs) can be called multiple times depending on the TYPE (sort, display, type). Within the RENDER function I needed to add logic that returns the value that I need for the given type that's being rendered. When I want the custom sort value (the Id, and not the custom image tag), make sure I have logic for rendering the SORT type (and I guess, where TYPE = 'type' too). Otherwise, render my custom IMG that I need. Easy, right?

Here's the new code that correctly handles the sorting and the display as I require. Check the type and do what you need to...

 {
                     "targets": 1,
                     "render":
                         function (data, type, row) {
                             var element = "<img id='status_" + row["UserId"] + "' src='" + data["ImageUrl"] + "' title='" + data["Description"] + "";

                             if (type === "sort" || type === 'type') {
                                 return data["Id"];
                             }
                             else {
                                 if (data["Id"] == "2") // add in-process name
                                 {
                                     var userId = row["ProcessUserId"].trim();
                                     element = element + " by " + userId;
                                 }
                                 return element + "'/>";
                             }
                         },
                     "searchable": false,
                     "sortable": true,
                 },
Sign up to request clarification or add additional context in comments.

Comments

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.