Using a function in cell template
Asked Answered
R

4

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?

Roche answered 12/10, 2015 at 12:39 Comment(7)
Have you tried the date filter?Epistle
don't use {{}} on scope function variablesUpstretched
@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.Roche
@Upstretched I tried but the whole expression is considered as a String. Then the grid displays formatDate(row.entity.date) in every cells :DRoche
@ArnaudDenoyelle is this what you are looking for?Epistle
Here is an example fiddle of what I think you are looking for, maybe?Epistle
@Asok Yes :) I did not know about grid.appScope. Please post it as an answer and I will accept it.Roche
E
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

Epistle answered 12/10, 2015 at 14:49 Comment(4)
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.Robinetta
@Robinetta 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 allowedEpistle
Fiddle dead linkSalto
@Salto Assuming you mean the link in the answer, it is fixed. Thanks.Epistle
U
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>
Upstretched answered 12/10, 2015 at 12:52 Comment(3)
The cells are rendered empty. A console.log() in $scope.formatDate shows that the function is not called. But I cannot see any errors in the console.Roche
create a directive , scope inside grid won't be your controller scopeUpstretched
You need {{ grid.appScope.formatDate(row.entity.date) }}Solo
T
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;
        }
    }
Theolatheologian answered 17/5, 2018 at 2:29 Comment(0)
M
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>"

Moneybags answered 8/9, 2022 at 22:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.