0

Hi I have a situation in AngluarJS that the HTML is generated by back-end and the only thing that front-end should do is to put the HTML which is mostly table tags into the ng-bind-html and show it to the user. But now these tables should be sort-able too. How can I do it?

The thing that I've already done is to create my own directive using this so make the static string HTML take some actions too. But having them sorted is something else. In other word I want to make my fully generated table with all <tr> and <td> to get sorted by my actions.

Here is my simplified code (compile is my directive):

JS:
// The string is fully generated by back-end
$scope.data.html = 
'<table> <tr> <th ng-click="sortByHeader($event)"> Name </th> 
              <th ng-click="sortByHeader($event)"> Age </th> </tr>
              <tr> <td> Sara </td> <td> 15 </td> </tr>
              <tr> <td> David </td> <td> 20 </td> </tr>'

HTML: 
<div compile="data.html"></div>

The ng-click="sortByHeader($event) is something that back-end can prepare for me so I can use it thanks to the compile I wrote that let me find out which header has been clicked. Other than that there is nothing I can do. Unless you can help me :D

Thanks in advance, I hope my question was clear.

erfoon
  • 142
  • 1
  • 10

2 Answers2

1

Since you tagged your question with sorttable.js I'm going to assume that you are using that script to sort your tables. Now, if I understand it correctly, sorttable.js parses your HTML for any tables with the class sortable. Your table is apparently loaded dynamically, therefore sorttable.js does not know about it when it parses the HTML.

But you can tell it to make a dynamically added table sortable, too.

Relevant part taken from the following page: https://kryogenix.org/code/browser/sorttable/#ajaxtables

Sorting a table added after page load

Once you've added a new table to the page at runtime (for example, by doing an Ajax request to get the content, or by dynamically creating it with JavaScript), get a reference to it (possibly with var newTableObject = document.getElementById(idOfTheTableIJustAdded) or similar), then do this:

sorttable.makeSortable(newTableObject);

You should be able to do that with angular. If not, I can try to put something together later.

Florian Lim
  • 5,332
  • 2
  • 27
  • 28
  • Thanks for you answer. Actually it's funny that I tagged `sorttable.js` because I didn't notice `js` and I tagged it as a general subject. But now I looked at the library and saw it can be a solution for my situation, but as I'm no experienced in AngularJS I don't know how to include this library (which is only a js file) in my project.The instruction says you should simply put it in a – erfoon Jan 30 '19 at 13:21
  • @ErfanSamieyan Side note: You stated in your comment to the other answer that your goal is to reduce the work on the client. May I suggest that unless you have a very good reason to return preformatted HTML by your server, it may be better to return pure data and then use `ng-repeat` to populate the table in your front-end. It will allow you to use other popular directives for tables and have a better decoupling of client and server. ---- Now, regarding your question: You need to add the script with a normal ` – Florian Lim Jan 30 '19 at 13:50
  • I 100% agree with you about rendering the Table dynamically in front-end, but the case that I'm working has a old structure which they don't to change it. So I should deal with it in front-end. However I should either use this `sorttable.js` file or [jQuery Datatables](https://datatables.net/) which are both seems to be a working solution. Thank you for your help :) – erfoon Jan 30 '19 at 17:17
0

Is the answer to the question "Does the rendered table have to exactly match the HTML retrieved by the backend?" a kind of "No"?

If that's the case, then here's a hacky way of gaining control of the table contents by parsing and capturing stuff from the backend HTML string using regular expressions.

For example: grab all row data and apply sorting client side

// Variables to be set by your sortByHeader functions in order to do client-side sorting
$scope.expression = null;
$scope.direction = null;

var regexToGetTableHead = /<table>\s*(.*<\/th>\s*<\/tr>)/g;
$scope.tableHead = regexToGetTableHead.exec($scope.data.html);

$scope.tableRows = [];

var regexToGetRowContents = /<tr>\s*<td>\s*(\w*)\s*<\/td>\s*<td>\s*(\w*)\s*<\/td>\s*<\/tr>/g;

var match;
while ((match = regexToGetRowContents.exec($scope.data.html)) != null) {
    $scope.tableRows.push({
        "name": match[1],
        "age": match[2] 
    });
}

And HTML

<table>
    <thead compile="tableHead"></thead>

    <tbody>
        <tr ng-repeat="row in tableRows | orderBy: expression : direction">
            <td>{{row.name}}</td>
            <td>{{row.age}}</td>
        </tr>
    </tbody>
</table>
Protozoid
  • 1,207
  • 1
  • 8
  • 16
  • Thanks this is actually a way but the whole point of the HTML being generated is to reduce the job of front-end but now again parsing the data from it and reusing it doesn't seem to be the best idea. – erfoon Jan 30 '19 at 13:23
  • I see @ErfanSamieyan; I was treating this more as a limitation from whatever backend system as opposed to a preferred design decision. (I'm not a fan of server-side HTML unless really necessary) I guess what you're after then is to have the `sortByHeader` function defined by the backend, which when clicked would reload the table contents with newly sorted table HTML from the backend. – Protozoid Jan 30 '19 at 15:36