LIDOR SYSTEMS

Advanced User Interface Controls and Components

Angular Grid with Custom Cell Templates

Created: 22 April 2016

Usually cells in Angular Grid directive display only single line of text. If we want to show additional content like images, buttons, progress bars or other custom HTML elements, we need to use a template.


Grid directive is part of IntegralUI Studio for Web
a suite of UI Components for development of web apps

In above example, we have several columns wit different content in their cells. Some grid cells show an icon and text, other shows a progress bar and the last one shows a button. All of these columns use a template as a model by which grid cell content is created.

Create Custom Templates for Grid Cells

Each column object has a field named cellTemplateUrl that specifies the template identifier by which content for the grid cells in that column is created. The template needs to be set by using the <script> tag, so that AngularJS will locate it from the template cache. For example:

// Set a unique identifier for the grid

$scope.gridName = "gridSample";

 

// An array object that holds grid columns

$scope.columns = [

{ id: 1, headerText: "Company", width: 240 },

{ id: 2, headerText: "Price", width: 80, contentAlignment: 'right', cellTemplateUrl: "'cell-price.html'" },

{ id: 3, headerText: "Change", width: 70, contentAlignment: 'center' },

{ id: 4, headerText: "Change %", width: 120, minWidth: 120, headerAlignment: 'center', cellTemplateUrl: "'cell-change.html'" },

{ id: 5, headerText: "Volume", width: 110, headerAlignment: 'center', contentAlignment: 'right' },

{ id: 6, headerText: "Country", width: 130, cellTemplateUrl: "'cell-country.html'" },

{ id: 7, width: 75, cellTemplateUrl: "'cell-button.html'" }

];

 

// An array object that holds grid rows

$scope.rows = [

{

id: 1,

cells: [

{ cid: 1, text: "Lacus Aliquam Consulting" },

{

cid: 2,

templateObj: {

indicator: true,

text: "$32.46"

}

},

{ cid: 3, text: "+5.23" },

{

cid: 4,

templateObj: {

progress: getProgressWidth(7.15),

text: "+7.15%"

}

},

{ cid: 5, text: "2,749,325" },

{

cid: 6,

templateObj: {

country: 'brazil',

text: "Brazil"

}

},

{

cid: 7,

templateObj: {

id: 1,

onDeleteRow: function(obj){ return $scope.onDeleteRow(obj) }

}

}

]

},

{

id: 2,

cells: [

{ cid: 1, text: "Augue LLC" },

{

cid: 2,

templateObj: {

indicator: true,

text: "$7.43"

}

},

{ cid: 3, text: "+2.83" },

{

cid: 4,

templateObj: {

progress: getProgressWidth(18.5),

text: "+18.50%"

}

},

{ cid: 5, text: "12,251,937" },

{

cid: 6,

templateObj: {

country: 'germany',

text: "Germany"

}

},

{

cid: 7,

templateObj: {

id: 2,

onDeleteRow: function(obj){ return $scope.onDeleteRow(obj) }

}

}

]

},

 

// ... Data for other rows goes here

];

<script type="text/ng-template" id="'cell-price.html'">

<div class="price-cell">

<span ng-class="obj.indicator == true ? 'icons price-up' : obj.indicator == false ? 'icons price-down' : 'icons'"></span>

{{obj.text}}

</div>

</script>

<script type="text/ng-template" id="'cell-change.html'">

<div class="change-cell">

<span>{{obj.text}}</span>

<p iui-style="width:{{obj.progress}}px" ng-class="{ 'progress-blue': obj.indicator != false, 'progress-red': obj.indicator == false }"></p>

</div>

</script>

<script type="text/ng-template" id="'cell-button.html'">

<div class="button-cell">

<button ng-click="obj.onDeleteRow(obj)">Delete</button>

</div>

</script>

<script type="text/ng-template" id="'cell-country.html'">

<div class="country-cell">

<span iui-class="countries {{obj.country}}"></span>

<span>{{obj.text}}</span>

</div>

</script>

Each template can have custom HTML elements arranged in different layouts along with custom objects within. In order to access these objects and add some dynamic functionality like user clicks, each cell object for column that have a template set, need to have its templateObj field. This field accepts any custom object set in your controller application.

Related: InCell Editing in AngularJS Grid

By adding arbitrary objects and values in the templateObj, you can create a link between the template and the specific grid cell.

Grid Cell with Image and Text

The template that displays an icon on the left side and a text in a grid cell is simple. A <span> element is used to show an icon by setting its background to render a small icon, and for the text a standard binding expression is used. In that way whenever a text value in templateObj for that grid cell changes, it will be automatically updated.

<script type="text/ng-template" id="'cell-price.html'">

<div class="price-cell">

<span ng-class="obj.indicator == true ? 'icons price-up' : obj.indicator == false ? 'icons price-down' : 'icons'"></span>

{{obj.text}}

</div>

</script>

<script type="text/ng-template" id="'cell-change.html'">

<div class="change-cell">

<span>{{obj.text}}</span>

<p iui-style="width:{{obj.progress}}px" ng-class="{ 'progress-blue': obj.indicator != false, 'progress-red': obj.indicator == false }"></p>

</div>

</script>

<script type="text/ng-template" id="'cell-button.html'">

<div class="button-cell">

<button ng-click="obj.onDeleteRow(obj)">Delete</button>

</div>

</script>

<script type="text/ng-template" id="'cell-country.html'">

<div class="country-cell">

<span iui-class="countries {{obj.country}}"></span>

<span>{{obj.text}}</span>

</div>

</script>

/* Cell with Image and Text */

.icons

{

background-image: url(../resources/icons.png);

background-repeat: no-repeat;

display: inline-block;

float: left;

overflow: hidden;

padding: 0;

margin: 1px 1px 0 0;

width: 16px;

height: 16px;

vertical-align: middle;

}

.price-up

{

background-position: -64px -32px;

}

.price-down

{

background-position: -80px -32px;

}

Depending on the indicator field value, a different icon is shown: green up arrow for positive numbers, and red down arrow for negative numbers.

Progress Bar in Grid Cell

In order to show a progress bar inside the grid cell, a paragraph element is used with its width and background set dynamically depending on templateObj value. For this purpose we are using the ngClass directive to dynamically change the CSS class for the HTML element.

<script type="text/ng-template" id="'cell-price.html'">

<div class="price-cell">

<span ng-class="obj.indicator == true ? 'icons price-up' : obj.indicator == false ? 'icons price-down' : 'icons'"></span>

{{obj.text}}

</div>

</script>

<script type="text/ng-template" id="'cell-change.html'">

<div class="change-cell">

<span>{{obj.text}}</span>

<p iui-style="width:{{obj.progress}}px" ng-class="{ 'progress-blue': obj.indicator != false, 'progress-red': obj.indicator == false }"></p>

</div>

</script>

<script type="text/ng-template" id="'cell-button.html'">

<div class="button-cell">

<button ng-click="obj.onDeleteRow(obj)">Delete</button>

</div>

</script>

<script type="text/ng-template" id="'cell-country.html'">

<div class="country-cell">

<span iui-class="countries {{obj.country}}"></span>

<span>{{obj.text}}</span>

</div>

</script>

/* Cell with ProgressBar */

.change-cell > span

{

display: inline-block;

margin: 0 2px 0 0;

overflow: hidden;

padding: 0;

text-align: right;

vertical-align: middle;

width: 60px;

}

.change-cell > p

{

display: inline-block;

margin: 0;

padding: 0;

height: 16px;

vertical-align: middle;

}

.progress-blue

{

background: #0080ef;

}

.progress-red

{

background: #ef8000;

}

In this case, the indicator value determines the background color of the progress bar. If the indicator value is positive, the progress bar will appear in blue, otherwise in orange.

How to Add Button to Grid Cell

In similar way like in previous cases, to add a button in the grid cell, we will create a template that uses the <button> element.

<script type="text/ng-template" id="'cell-price.html'">

<div class="price-cell">

<span ng-class="obj.indicator == true ? 'icons price-up' : obj.indicator == false ? 'icons price-down' : 'icons'"></span>

{{obj.text}}

</div>

</script>

<script type="text/ng-template" id="'cell-change.html'">

<div class="change-cell">

<span>{{obj.text}}</span>

<p iui-style="width:{{obj.progress}}px" ng-class="{ 'progress-blue': obj.indicator != false, 'progress-red': obj.indicator == false }"></p>

</div>

</script>

<script type="text/ng-template" id="'cell-button.html'">

<div class="button-cell">

<button ng-click="obj.onDeleteRow(obj)">Delete</button>

</div>

</script>

<script type="text/ng-template" id="'cell-country.html'">

<div class="country-cell">

<span iui-class="countries {{obj.country}}"></span>

<span>{{obj.text}}</span>

</div>

</script>

/* Cell with Button */

.button-cell

{

text-align: center;

}

.button-cell button

{

background: #004896;

border: 0;

color: white;

padding: 5px;

width: 75px;

}

.button-cell button:hover

{

background: #0080ef;

}

Whenever this button is clicked, the onDeleteRow function will execute. This function must be set in templateObj, because templates are compiled against the grid scope. In that way, the AngularJS can find the function in grid data and create a link with the template.

$scope.onDeleteRow = function(obj){

var row = $gridService.findRowById($scope.gridName, obj.id);

if (row)

$gridService.removeRow($scope.gridName, row);

}

In our example, this function removes the row to which this grid cell belongs.

Related: Custom DropDown Editor in AngularJS Grid

Conclusion

By creating custom templates, you can add any number of different HTML elements and arrange them in different layouts within the grid cell space. IntegralUI Grid directive for AngularJS allows you to customize the grid layout in many ways. You can have cells that shows text in multiple lines, with images, buttons, progress bars or any other custom editors.

Did you Like this Article?


Enter your e-mail address below and you will receive latest articles as well as news on upcoming events and special offers.