14

I am using angularjs with ui-grid. One column of the grid contains a timestamp that I would like to render as a properly formatted date.

Up to now, I tried like this but the function is never called.

  $scope.formatDate = function(date) {
    return '42';
  };

  $scope.columns = [
    {field: 'date', cellTemplate: '<div class="ui-grid-cell-contents">formatDate({{row.entity.date}})</div>'},
    {field: 'title'},
    {field: 'quantity'},
    //[...]
  ];

Instead, the function call is considered as a string literal. As a result, the column always displays formatDate(*timestamp*).

I only found a non-satisfying way of achieving it by defining a function on each single row when receiving them :

  $scope.columns = [
    {field: 'getFormattedDate()'},
    //[...]
  ];

  $http.post('/api/data/').success(function (data) {
    $scope.gridOptions.data = data.elements;

    $scope.gridOptions.data.forEach(function(row) {
      row.getFormattedDate = function() {
        return '42';
      }
    })
  });

Any better suggestion?

Arnaud Denoyelle
  • 29,980
  • 16
  • 92
  • 148
  • Have you tried the [date filter](https://docs.angularjs.org/api/ng/filter/date)? – jnthnjns Oct 12 '15 at 12:42
  • don't use `{{}}` on scope function variables – charlietfl Oct 12 '15 at 12:45
  • @Asok Yes, the date filter works fine. Sorry but the question is actually meant to be more general than "how to parse a date". I would like to be able to call a method for others columns which contains something else than dates. – Arnaud Denoyelle Oct 12 '15 at 12:46
  • @charlietfl I tried but the whole expression is considered as a String. Then the grid displays `formatDate(row.entity.date)` in every cells :D – Arnaud Denoyelle Oct 12 '15 at 12:47
  • @ArnaudDenoyelle is [this what you are looking for](http://stackoverflow.com/a/28127498/1134705)? – jnthnjns Oct 12 '15 at 14:05
  • [Here](http://jsfiddle.net/jon23781/5hyurkc1/2/) is an example fiddle of what I think you are looking for, maybe? – jnthnjns Oct 12 '15 at 14:08
  • @Asok Yes :) I did not know about `grid.appScope`. Please post it as an answer and I will accept it. – Arnaud Denoyelle Oct 12 '15 at 14:36

4 Answers4

19

If you want to access controller scope level functions using ui-grid you can use grid.appScope, here is a quick example:

{
    name: 'date',
    cellTemplate: '<div class="ui-grid-cell-contents">{{grid.appScope.parseDate(row.entity.date)}}</div>'
}

Full Example:

angular.module('myApp', ['ui.grid'])
    .controller('myCtrl', ['$scope', function ($scope) {

    $scope.parseDate = function (p) {
        // Just return the value you want to output
        return p;
    }

    $scope.parseName = function (p) {
        // Just return the value you want to output
        return p;
    }

    $scope.gridOptions = {
        data: [{
            name: "Foo",
            date: "2015-10-12"
        }, {
            name: "Bar",
            date: "2014-10-12"
        }],
        columnDefs: [{
            name: 'name',
            cellTemplate: '<div class="ui-grid-cell-contents">{{grid.appScope.parseName(row.entity.name)}}</div>'
        }, {
            name: 'date',
            cellTemplate: '<div class="ui-grid-cell-contents">{{grid.appScope.parseDate(row.entity.date)}}</div>'
        }]
    };
}]);

Fiddle Example

jnthnjns
  • 8,962
  • 4
  • 42
  • 65
  • This is working fine but when I am trying to return a an element its not working. How can we return an inline HTML? Here I am trying to Show custom button on Group header lavel by using cellTemplate. – aswininayak Jun 18 '18 at 21:12
  • @aswininayak If you want to use html in AngularJS you need to use `ngBindHtml` and `ngSanitize` but, my understanding is that `ngSanitize` does not allow HTML form elements, it strips them. [In this example you can see how the input elements are removed and the div is allowed](http://jsfiddle.net/jnthnjns/5hyurkc1/51/) – jnthnjns Jul 11 '18 at 12:26
  • Fiddle dead link – Phil3992 Jul 16 '18 at 10:40
  • 1
    @Phil3992 Assuming you mean the link in the answer, it is fixed. Thanks. – jnthnjns Jul 16 '18 at 11:53
4

To use function output the whole function call, not the arguments , needs to be wrapped in expression braces

<div class="ui-grid-cell-contents">{{ formatDate(row.entity.date) }}</div>
charlietfl
  • 170,828
  • 13
  • 121
  • 150
0

It's worth noting that the cellTemplate will not do anything if you don't include HTML in the format:

will not hit the formatting method "formatRating()":

            columnDefs: [
            {
                name: 'starRating', headerCellClass: 'blue', headerTooltip: 'Star Rating',
                cellTemplate: '{{grid.appScope.formatRating(row.entity.starRating)}}'
            },

Works with the addition of a <span> in the cellTemplate:

            columnDefs: [
            {
                name: 'starRating', headerCellClass: 'blue', headerTooltip: 'Star Rating',
                cellTemplate: '<span>{{grid.appScope.formatRating(row.entity.starRating)}}</span>'
            },

my format method:

        $scope.formatRating = function (starRating) {
        switch (starRating) {
            case "ONE": return "1/5"; break;
            case "TWO": return "2/5"; break;
            case "THREE": return "3/5"; break;
            case "FOUR": return "4/5"; break;
            case "FIVE": return "5/5"; break;
        }
    }
Adam Hey
  • 1,512
  • 1
  • 20
  • 24
0

I use the controllerAs: 'vm' option on my controller, so I had to do the following to call functions in a cellTemplate.

Define the function on the vm scope like this:

vm.$scope.getBitFlag = (flags, value) => (flags & value) ? "✅" : "⬜️";

Then use it like this:

cellTemplate: "<div>{{ grid.appScope.getBitFlag(row.entity.prefValue, 1) }}</div>"

Todd Hale
  • 480
  • 8
  • 15