diff --git a/misc/demo/grid-directive.html b/misc/demo/grid-directive.html
index dac49a0733..5331e2e3d7 100644
--- a/misc/demo/grid-directive.html
+++ b/misc/demo/grid-directive.html
@@ -35,7 +35,7 @@
Grid
-
+
diff --git a/src/js/core/directives/ui-grid-row.js b/src/js/core/directives/ui-grid-row.js
index c513668a18..3efd036b98 100644
--- a/src/js/core/directives/ui-grid-row.js
+++ b/src/js/core/directives/ui-grid-row.js
@@ -23,10 +23,25 @@
$scope.grid = uiGridCtrl.grid;
$scope.colContainer = containerCtrl.colContainer;
- grid.getRowTemplateFn.then(function (templateFn) {
- templateFn($scope, function(clonedElement, scope) {
- $elm.replaceWith(clonedElement);
+ // Function for attaching the template to this scope
+ function compileTemplate() {
+ var compiledElementFn = $scope.row.compiledElementFn;
+
+ compiledElementFn($scope, function (clonedElement, scope) {
+ $elm.empty().append(clonedElement);
});
+ }
+
+ // Initially attach the compiled template to this scope
+ compileTemplate();
+
+ // If the row's compiled element function changes, we need to replace this element's contents with the new compiled template
+ $scope.$watch('row.compiledElementFn', function (newFunc, oldFunc) {
+ if (newFunc !== oldFunc) {
+ newFunc($scope, function (clonedElement, scope) {
+ $elm.empty().append(clonedElement);
+ });
+ }
});
},
post: function($scope, $elm, $attrs, controllers) {
diff --git a/src/js/core/services/gridClassFactory.js b/src/js/core/services/gridClassFactory.js
index 887e6577ef..a48227cddd 100644
--- a/src/js/core/services/gridClassFactory.js
+++ b/src/js/core/services/gridClassFactory.js
@@ -43,6 +43,9 @@
grid.registerColumnBuilder(service.defaultColumnBuilder);
+ // Row builder for custom row templates
+ grid.registerRowBuilder(service.rowTemplateAssigner);
+
// Reset all rows to visible initially
grid.registerRowsProcessor(function allRowsVisible(rows) {
rows.forEach(function (row) {
@@ -179,8 +182,49 @@
col.compiledElementFnDefer = $q.defer();
return $q.all(templateGetPromises);
- }
+ },
+
+ rowTemplateAssigner: function rowTemplateAssigner(row) {
+ var grid = this;
+
+ // Row has no template assigned to it
+ if (!row.rowTemplate) {
+ // Use the default row template from the grid
+ row.rowTemplate = grid.options.rowTemplate;
+ // Use the grid's function for fetching the compiled row template function
+ row.getRowTemplateFn = grid.getRowTemplateFn;
+
+ // Get the compiled row template function...
+ grid.getRowTemplateFn.then(function (rowTemplateFn) {
+ // And assign it to the row
+ row.compiledElementFn = rowTemplateFn;
+ });
+ }
+ // Row has its own template assigned
+ else {
+ // Create a promise for the compiled row template function
+ var perRowTemplateFnPromise = $q.defer();
+ row.getRowTemplateFn = perRowTemplateFnPromise.promise;
+
+ // Get the row template
+ gridUtil.getTemplate(row.rowTemplate)
+ .then(function (template) {
+ // Compile the template
+ var rowTemplateFn = $compile(template);
+
+ // Assign the compiled template function to this row
+ row.compiledElementFn = rowTemplateFn;
+
+ // Resolve the compiled template function promise
+ perRowTemplateFnPromise.resolve(rowTemplateFn);
+ },
+ function (res) {
+ // Todo handle response error here?
+ throw new Error("Couldn't fetch/use row template '" + row.rowTemplate + "'");
+ });
+ }
+ }
};
//class definitions (moved to separate factories)
diff --git a/test/unit/core/directives/ui-grid-row.spec.js b/test/unit/core/directives/ui-grid-row.spec.js
new file mode 100644
index 0000000000..e0eba78515
--- /dev/null
+++ b/test/unit/core/directives/ui-grid-row.spec.js
@@ -0,0 +1,97 @@
+ddescribe('uiGridRow', function () {
+ var grid, data, columnDefs, $scope, $compile, $document, recompile, uiGridConstants, GridRow, gridUtil;
+
+ data = [
+ { "name": "Bob", "age": 35 },
+ { "name": "Bill", "age": 25 },
+ { "name": "Sam", "age": 17 },
+ { "name": "Jane", "age": 19 }
+ ];
+
+ columnDefs = [
+ { name: 'name' },
+ { name: 'age' }
+ ];
+
+ beforeEach(module('ui.grid'));
+
+ beforeEach(inject(function (_$compile_, $rootScope, _$document_, _uiGridConstants_, _GridRow_, _gridUtil_) {
+ $scope = $rootScope;
+ $compile = _$compile_;
+ $document = _$document_;
+ uiGridConstants = _uiGridConstants_;
+ GridRow = _GridRow_;
+ gridUtil = _gridUtil_;
+
+ $scope.gridOpts = {
+ columnDefs: columnDefs,
+ data: data,
+ onRegisterApi: function( gridApi ){ $scope.gridApi = gridApi; }
+ };
+
+ $scope.extScope = 'test';
+
+ recompile = function () {
+ grid = angular.element('');
+
+ $compile(grid)($scope);
+
+ $scope.$digest();
+ };
+
+ recompile();
+ }));
+
+ describe('with different row templates', function () {
+ beforeEach(inject(function($templateCache) {
+ $templateCache.put('customRowTemplate', 'The name is: {{ row.entity.name }}
');
+
+ $scope.gridApi.grid.registerRowsProcessor(function alterTemplates(rows, cols) {
+ var grid = this;
+
+ rows.forEach(function (row) {
+ if (row.entity.name === 'Sam') {
+ row.rowTemplate = 'customRowTemplate';
+ gridUtil.getTemplate(row.rowTemplate)
+ .then(function (template) {
+ row.compiledElementFn = $compile(template);
+ });
+ }
+ });
+
+ return rows;
+ });
+
+ $scope.gridApi.grid.refresh();
+ $scope.$digest();
+ }));
+
+ it('should allow rows to compile with different templates', function() {
+ // The third row in the template should have a different template
+ var thirdRow = $(grid).find('.ui-grid-row:nth-child(3)');
+
+ expect(thirdRow.text()).toEqual('The name is: Sam');
+ });
+
+ it('should change templates properly after a sort', function () {
+ var refreshed = false;
+ runs(function () {
+ $scope.gridApi.grid.sortColumn($scope.gridApi.grid.columns[0], uiGridConstants.ASC)
+ .then(function () {
+ $scope.gridApi.grid.refresh();
+ refreshed = true;
+ });
+
+ $scope.$digest();
+ });
+
+ waitsFor(function () { return refreshed; }, 10000);
+
+ runs(function () {
+ var fourthRow = $(grid).find('.ui-grid-row:nth-child(4)');
+
+ expect(fourthRow.text()).toEqual('The name is: Sam');
+ });
+ });
+ });
+});
\ No newline at end of file