Skip to content

Commit

Permalink
Merge branch 'feat-row-templates'
Browse files Browse the repository at this point in the history
  • Loading branch information
c0bra committed Dec 22, 2014
2 parents cf70e90 + 64d3918 commit ed95cfe
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 8 deletions.
2 changes: 1 addition & 1 deletion misc/demo/grid-directive.html
Expand Up @@ -35,7 +35,7 @@

<!-- <div class="row main"> -->
<h2>Grid</h2>
<div ui-grid="gridOptions" class="grid" ui-grid-pinning ui-grid-resize-columns></div>
<div ui-grid="gridOptions" class="grid" ui-grid-resize-columns></div>
<!-- <div class="placeholder"> -->
<!-- </div> -->

Expand Down
2 changes: 1 addition & 1 deletion src/js/core/directives/ui-grid-cell.js
Expand Up @@ -87,8 +87,8 @@ angular.module('ui.grid').directive('uiGridCell', ['$compile', '$parse', 'gridUt
rowWatchDereg();
};


$scope.$on( '$destroy', deregisterFunction );
$elm.on( '$destroy', deregisterFunction );
}
};
}
Expand Down
38 changes: 33 additions & 5 deletions src/js/core/directives/ui-grid-row.js
Expand Up @@ -23,18 +23,46 @@
$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
var clonedElement, cloneScope;
function compileTemplate() {
var compiledElementFn = $scope.row.compiledElementFn;

// Create a new scope for the contents of this row, so we can destroy it later if need be
var newScope = $scope.$new();

compiledElementFn(newScope, function (newElm, scope) {
// If we already have a cloned element, we need to remove it and destroy its scope
if (clonedElement) {
clonedElement.remove();
cloneScope.$destroy();
}

// Empty the row and append the new element
$elm.empty().append(newElm);

// Save the new cloned element and scope
clonedElement = newElm;
cloneScope = newScope;
});
}

// 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) {
compileTemplate();
}
});
},
post: function($scope, $elm, $attrs, controllers) {
var uiGridCtrl = controllers[0];
var containerCtrl = controllers[1];

//add optional reference to externalScopes function to scope
//so it can be retrieved in lower elements
// Sdd optional reference to externalScopes function to scope
// so it can be retrieved in lower elements
$scope.getExternalScopes = uiGridCtrl.getExternalScopes;
}
};
Expand Down
46 changes: 45 additions & 1 deletion src/js/core/services/gridClassFactory.js
Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
Expand Down
97 changes: 97 additions & 0 deletions 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('<div style="width: 500px; height: 300px" ui-grid="gridOpts"></div>');

$compile(grid)($scope);

$scope.$digest();
};

recompile();
}));

describe('with different row templates', function () {
beforeEach(inject(function($templateCache) {
$templateCache.put('customRowTemplate', '<div><div>The name is: {{ row.entity.name }}</div></div>');

$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');
});
});
});
});

0 comments on commit ed95cfe

Please sign in to comment.