Angular ng-table dynamic headers doesn't work inside
Asked Answered
K

3

5

I am using ng-table with dynamic columns, using the creator's example found at http://bazalt-cms.com/ng-table/example/20

It worked just fine, until i tried to wrap on a directive with transclude, witch caused the headers to disappear as seen on http://plnkr.co/edit/mjYVEf.

index.html

<!DOCTYPE html>
<html>
  <head>
    <script data-require="angular.js@*" data-semver="1.2.0-rc3-nonmin" src="http://code.angularjs.org/1.2.0-rc.3/angular.js"></script>
    <script data-require="ng-table@*" data-semver="0.3.1" src="http://bazalt-cms.com/assets/ng-table/0.3.1/ng-table.js"></script>
    <script data-require="[email protected]" data-semver="0.1.0" src="http://bazalt-cms.com/assets/ng-table-export/0.1.0/ng-table-export.js"></script>

    <link data-require="ng-table@*" data-semver="0.3.0" rel="stylesheet" href="http://bazalt-cms.com/assets/ng-table/0.3.0/ng-table.css" />
    <link data-require="bootstrap-css@*" data-semver="3.0.0" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" />

    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>
  <body ng-app="main" ng-controller="DemoCtrl">
    <div ng-controller="DemoCtrl">
    <transclude-example>
      Columns:
      <label class="checkbox" ng-repeat="column in columns">
          <input type="checkbox" ng-model="column.visible" /> {{column.title}}
      </label>

      <table ng-table="tableParams" show-filter="true" class="table">
          <thead>
          <tr>
              <th ng-repeat="column in columns" ng-show="column.visible"
                  class="text-center sortable" ng-class="{
                      'sort-asc': tableParams.isSortBy(column.field, 'asc'),
                      'sort-desc': tableParams.isSortBy(column.field, 'desc')
                    }"
                  ng-click="tableParams.sorting(column.field, tableParams.isSortBy(column.field, 'asc') ? 'desc' : 'asc')">
                  {{column.title}}
              </th>
              <!--<th>Columns:{{columns.length}}</th>-->
          </tr>
          </thead>
          <tbody>
          <tr ng-repeat="user in $data">
              <td ng-repeat="column in columns" ng-show="column.visible" sortable="column.field">
                  {{user[column.field]}}
              </td>
          </tr>
          </tbody>
      </table>
    </transclude-example>
  </body>
</html>

script.js

var app = angular.module('main', ['ngTable']).
        controller('DemoCtrl', function($scope, $filter, ngTableParams) {
            var data = [{name: "Moroni", age: 50},
                {name: "Tiancum", age: 43},
                {name: "Jacob", age: 27},
                {name: "Nephi", age: 29},
                {name: "Enos", age: 34},
                {name: "Tiancum", age: 43},
                {name: "Jacob", age: 27},
                {name: "Nephi", age: 29},
                {name: "Enos", age: 34},
                {name: "Tiancum", age: 43},
                {name: "Jacob", age: 27},
                {name: "Nephi", age: 29},
                {name: "Enos", age: 34},
                {name: "Tiancum", age: 43},
                {name: "Jacob", age: 27},
                {name: "Nephi", age: 29},
                {name: "Enos", age: 34}];
            $scope.columns = [
                { title: 'Name', field: 'name', visible: true, filter: { 'name': 'text' } },
                { title: 'Age', field: 'age', visible: true }
            ];
            $scope.tableParams = new ngTableParams({
                page: 1,            // show first page
                count: 10,          // count per page
                filter: {
                    name: 'M'       // initial filter
                }
            }, {
                total: data.length, // length of data
                getData: function($defer, params) {
                    // use build-in angular filter
                    var orderedData = params.sorting() ?
                            $filter('orderBy')(data, params.orderBy()) :
                            data;

                    $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
                }
            });

            var originalData = [{name: "Moroni", age: 50},
                {name: "Tiancum", age: 43},
                {name: "Jacob", age: 27},
                {name: "Nephi", age: 29},
                {name: "Enos", age: 34},
                {name: "Tiancum", age: 43},
                {name: "Jacob", age: 27},
                {name: "Nephi", age: 29},
                {name: "Enos", age: 34},
                {name: "Tiancum", age: 43},
                {name: "Jacob", age: 27},
                {name: "Nephi", age: 29},
                {name: "Enos", age: 34},
                {name: "Tiancum", age: 43},
                {name: "Jacob", age: 27},
                {name: "Nephi", age: 29},
                {name: "Enos", age: 34}];
            $scope.originalColumns = [
                { title: 'Name', field: 'name', visible: true, filter: { 'name': 'text' } },
                { title: 'Age', field: 'age', visible: true }
            ];
            $scope.originalTableParams = new ngTableParams({
                page: 1,            // show first page
                count: 10,          // count per page
                filter: {
                    name: 'M'       // initial filter
                }
            }, {
                total: originalData.length, // length of data
                getData: function($defer, params) {
                    // use build-in angular filter
                    var orderedData = params.sorting() ?
                            $filter('orderBy')(originalData, params.orderBy()) :
                            originalData;

                    $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
                }
            });
        });

        app.directive('transcludeExample', function() {
          return {
              restrict: 'EA',
              template: '<div ><div><strong>Transcluded Example</strong></div><div ng-transclude></div></div>',
              replace: true,
              transclude: true
          };
});

Has anybody came across the same issue?

Kevel answered 8/7, 2014 at 9:1 Comment(0)
S
20

Define a template for a header, and set a template-header attribute of ng-table.

You can see the code http://plnkr.co/edit/EXVkjabwfjCreNZAY1c2?p=preview

Define template header

<script id="sample_ng_header" type="text/ng-template">
  <tr>
      <th ng-repeat="column in columns" ng-show="column.visible"
          class="text-center sortable" ng-class="{
              'sort-asc': tableParams.isSortBy(column.field, 'asc'),
              'sort-desc': tableParams.isSortBy(column.field, 'desc')
            }"
          ng-click="tableParams.sorting(column.field, tableParams.isSortBy(column.field, 'asc') ? 'desc' : 'asc')">
          {{column.title}}
      </th>
      <!--<th>Columns:{{columns.length}}</th>-->
  </tr>
</script>

Set template-header attribute of ng-table with your template

<table ng-table="tableParams" template-header="sample_ng_header" show-filter="true" class="table">
  <tbody>
  <tr ng-repeat="user in $data">
      <td ng-repeat="column in columns" ng-show="column.visible" sortable="column.field">
          {{user[column.field]}}
      </td>
  </tr>
  </tbody>
</table>
Spheroid answered 13/8, 2014 at 6:28 Comment(3)
@Seunghun can u point me any docs, i dont understand how this worked?Charleen
The plunker is broken because it refers to now-missing javascript file URLs. Try this one instead: plnkr.co/edit/UlGWV3QYJiz7eT5vrY3j?p=previewGrad
The ng-table project itself ( github.com/esvit/ng-table ) has links to examples.Mirisola
G
14

There is a newer way to do this since Feb 2015. I found the following originally linked from this issue on github, but the demo written has been updated since the original.

It makes use of the new ngTableDynamic directive.

The demo is at http://ng-table.com/#/formatting/demo-dynamic-js-values.

I think the main code to pay attention to, assuming you're familiar enough with the rest of ng-table, is

<table ng-table-dynamic="tableParams with cols" show-filter="true" class="table table-bordered table-striped">
    <tr ng-repeat="user in $data">
        <td ng-repeat="col in $columns">{{user[col.field]}}</td>
    </tr>
</table>

The tableParams with cols part will be parsed, split around the with to get the table configuration and the column definitions (e.g. $scope.tableParams and $scope.cols). You can see the column definitions with code like this:

var usernameCol = {
    title: 'Full Name',
    titleAlt: 'Name',
    sortable: 'name',
    filter: { name: 'select' },
    filterData: names,
    show: true,
    field: 'name'
};
var ageCol = { ... }

$scope.cols = [usernameCol, ageCol];
Grad answered 18/5, 2015 at 4:52 Comment(3)
This answer seems much cleaner and better formed than the accepted answer. The accepted answer will result in losing much of the standard ng-table formatting (i.e. sorting icons). Also - note that for each Col object, not all parameters are required. If you just want to sort, you can get away with only including 'title', 'field', and 'sortable'. Thanks for finding this answer!Worlock
works like a charm! thanks for posting this together with the example!Weinstein
@essaji I haven't used Angular for a long time. What do you think about the updated link?Grad
B
0

Here is my solution: The above solution with template-header did not work for me. The trick is to add the columns in the header and do the same in the data cells

<table ng-table="tableParams" class="table">
        <tr>
            <th ng-repeat="col in tableCols"
                class="text-left sortable header observation-header" ng-class="{
                        'sort-asc': tableParams.isSortBy(col.field, 'asc'),
                        'sort-desc': tableParams.isSortBy(col.field, 'desc')
                      }"
                ng-click="tableParams.sorting(col.field, tableParams.isSortBy(col.field, 'desc') ? 'asc' : 'desc')">
                <div>{{col.title}}</div>
            </th>
        </tr>
        <tbody>
            <tr ng-repeat="dataObj in $data">
                <td ng-repeat="col in tableCols" data-title="col.title" sortable="col.field">{{dataObj[col.field]}}</td>
            </tr>
        ></tbody>
    </table>
Banal answered 20/10, 2015 at 8:52 Comment(1)
What is tableCols?Detent

© 2022 - 2024 — McMap. All rights reserved.