Skip to content

Commit c608d80

Browse files
manvvyasmanvesh
authored andcommitted
Fixed width support for columns and table.
Allow resizing of columns. Update typescript definition file.
1 parent 531b996 commit c608d80

File tree

13 files changed

+4318
-2783
lines changed

13 files changed

+4318
-2783
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ The options object should be available on the parent scope of the `<ap-mesa>` el
117117
| showSortPriority | `boolean` | false | If true, will show a number indicating stacked sort priority of each column being sorted. |
118118
| clearFilterOnColumnHide | `boolean` | true | If true, a column's filter state will be removed when that column is hidden. |
119119
| clearSortOnColumnHide | `boolean` | true | If true, a column's sort state will be removed when that column is hidden. |
120+
| fixedWidthLayout | `boolean` | false | If true, the table's width can go beyond 100% width of the container. Use this with `lockWidth = true` for all columns. Note that horizontal scrollbars will appear for the table element. |
120121

121122
The options object is also the correct place to pass arbitrary data to table cell templates because it will be available as `options` in the table cell template scope. For example, if you want a click in a cell to call a function that is
122123
otherwise out of the scope of the table, you can do this:

angular-mesa.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ declare namespace angular.apMesa {
169169
clearFilterOnColumnHide?: boolean;
170170
// If true, a column's sort state will be removed when that column is hidden.
171171
clearSortOnColumnHide?: boolean;
172+
// If true, the table's width can go beyond 100% width of the container. Use this with `lockWidth = true` for all columns.
173+
// Note that horizontal scrollbars will appear for the table element. By default, the value is false.
174+
fixedWidthLayout?: boolean;
172175
}
173176
interface IRowScope extends ng.IScope {
174177
toggleRowExpand: Function;

app/scripts/controllers/disabled-columns.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
'use strict';
22

33
angular.module('apMesa.ghPage')
4-
.controller('DisabledColumnsCtrl', function($scope, $q, phoneData, $templateCache) {
4+
.controller('DisabledColumnsCtrl', function($scope, $q, phoneData, $templateCache, $rootScope) {
55

66
this.my_table_options = {
77
bodyHeight: 600,
88
rowPadding: 600,
99
storage: localStorage,
10-
storageKey: 'example'
10+
storageKey: 'example',
11+
fixedWidthLayout: false
1112
};
1213
this.my_table_options_paginated = angular.extend({ pagingStrategy: 'PAGINATE' }, this.my_table_options);
1314
this.my_selected_rows = [];
@@ -22,28 +23,34 @@ angular.module('apMesa.ghPage')
2223
'<i class="glyphicon glyphicon-triangle-right" ng-if="!rowIsExpanded"></i>' +
2324
'<i class="glyphicon glyphicon-triangle-bottom" ng-if="rowIsExpanded"></i>' +
2425
'{{ row.DeviceName }}' +
25-
'</a>'
26+
'</a>',
27+
width: '220px',
2628
},
2729
{
2830
id: 'brand',
2931
key: 'Brand',
3032
sort: 'string',
31-
label: 'Brand'
33+
label: 'Brand',
34+
width: '300px',
3235
},
3336
{
3437
id: 'edge',
3538
key: 'edge',
3639
label: 'Edge',
3740
sort: 'string',
38-
filter: 'like'
41+
filter: 'like',
42+
width: '320px',
3943
},
4044
{
4145
id: 'tech',
4246
key: 'technology',
4347
sort: 'string',
44-
label: 'Tech'
48+
label: 'Tech',
49+
width: '180px',
4550
}
4651
];
52+
53+
this.fixed_width_paging_scheme = 'scroll';
4754
this.my_enabled_columns = this.my_table_columns.map(function(c) { return c.id; });
4855
this.phoneData = phoneData;
4956
var _this = this;
@@ -62,4 +69,13 @@ angular.module('apMesa.ghPage')
6269
}
6370
};
6471

72+
this.toggleFixedWidth = function () {
73+
_this.my_table_options.fixedWidthLayout = !_this.my_table_options.fixedWidthLayout;
74+
_this.my_table_options_paginated.fixedWidthLayout = !_this.my_table_options_paginated.fixedWidthLayout;
75+
};
76+
77+
$rootScope.$on('apMesa:columnResized', function(event, column, columnWidth) {
78+
console.log('Column was resized', column, columnWidth);
79+
console.log(_this.my_table_columns);
80+
});
6581
});

app/views/disabled-columns.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ <h3>Enabled Columns</h3>
5656

5757
<pre>{{ vm.my_enabled_columns | json }}</pre>
5858

59+
<input id="fixedWidthLayout" type="checkbox" ng-checked="(vm.pagingScheme !== 'paginate' && vm.my_table_options.fixedWidthLayout) || (vm.pagingScheme == 'paginate' && vm.my_table_options_paginated.fixedWidthLayout)" ng-click="vm.toggleFixedWidth()"/>
60+
<label for="fixedWidthLayout">options.fixedWidthLayout</label>
61+
62+
5963
</div>
6064
</div>
6165
</div>

dist/ap-mesa.css

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
/* styles for both header- and rows- tables */
88

99
.ap-mesa {
10+
margin-bottom: 0;
11+
}
12+
13+
.ap-mesa.full-width {
1014
table-layout: fixed;
1115
width: 100%;
12-
margin-bottom: 0;
1316
}
1417

1518
/* the visible table header */
@@ -26,18 +29,22 @@
2629

2730
.mesa-rows-table thead {
2831
height: 0;
29-
visibility: hidden;
32+
visibility: collapse;
3033
}
3134

3235
.mesa-rows-table > thead > tr > th {
3336
border-width: 0;
34-
padding: 0 !important;
37+
/* padding: 0 !important; */
3538
}
3639

37-
.mesa-rows-table-wrapper {
40+
.mesa-rows-table-wrapper.auto-layout {
3841
overflow: auto;
3942
}
4043

44+
.mesa-rows-table-wrapper.fixed-width-layout {
45+
overflow-x: visible;
46+
}
47+
4148
.mesa-rows-table > tbody + tbody {
4249
border-top: none;
4350
}
@@ -63,7 +70,7 @@
6370
/* search input */
6471

6572
.ap-mesa tr.ap-mesa-filter-row td input {
66-
width: 100%;
73+
/* width: 100%; */
6774
border-radius: 2em;
6875
border: 1px solid #CCC;
6976
outline: none;
@@ -133,7 +140,7 @@ when a discreet width has been set on it */
133140
/* wrapper for text in a th */
134141

135142
.ap-mesa th .column-text {
136-
max-width: 100%;
143+
/* max-width: 100%; */
137144
overflow: hidden;
138145
display: block;
139146
}
@@ -250,6 +257,10 @@ table tbody .ap-mesa-dummy-row td {
250257
transition-delay: 0s;
251258
}
252259

260+
.ap-mesa-overflow-x-scroll {
261+
overflow-x: scroll;
262+
}
263+
253264
.ap-mesa-loading-display.ng-enter,
254265
.ap-mesa-loading-display.ng-enter.ng-leave.ng-leave-active {
255266
opacity: 0;
@@ -338,4 +349,12 @@ table tbody .ap-mesa-dummy-row td {
338349
-webkit-box-shadow: 0 1.5em 0 0;
339350
box-shadow: 0 1.5em 0 0;
340351
}
352+
}
353+
354+
.table-nonfluid {
355+
width: auto !important;
356+
}
357+
358+
.ap-mesa-nonfluid {
359+
overflow-x: scroll;
341360
}

dist/ap-mesa.js

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ angular.module('apMesa.controllers.ApMesaController', [
319319
} else {
320320
column.width = Math.max(new_width, CONSTANTS.minWidth);
321321
}
322+
$scope.$emit('apMesa:columnResized', column, column.width);
322323
$scope.$apply();
323324
});
324325
};
@@ -462,7 +463,8 @@ angular.module('apMesa.controllers.ApMesaController', [
462463
'glyphicon glyphicon-chevron-down'
463464
],
464465
onRegisterApi: function (api) {
465-
}
466+
},
467+
fixedWidthLayout: false
466468
};
467469
function defaults(obj) {
468470
if (typeof obj !== 'object') {
@@ -596,6 +598,7 @@ angular.module('apMesa.controllers.ApMesaController', [
596598
function postLink(scope, element) {
597599
var deregStorageWatchers = [];
598600
scope.scrollDiv = element.find('.mesa-rows-table-wrapper');
601+
scope.wrapperDiv = element.find('.ap-mesa-wrapper');
599602
scope.$watch('_columns', function (columns, oldColumns) {
600603
if (columns !== scope.columns) {
601604
resetColumns(scope);
@@ -639,6 +642,24 @@ angular.module('apMesa.controllers.ApMesaController', [
639642
resetState(scope);
640643
initOptions(scope);
641644
});
645+
scope.$watch('options.fixedWidthLayout', function (newValue, oldValue) {
646+
if (newValue !== oldValue) {
647+
if (angular.isString(scope.classes)) {
648+
if (newValue && scope.classes.indexOf('table-nonfluid') === -1) {
649+
scope.classes = scope.classes + ' table-nonfluid';
650+
} else if (!newValue && scope.classes.indexOf('table-nonfluid') > -1) {
651+
scope.classes = scope.classes.split('table-nonfluid').join('');
652+
}
653+
if (!newValue && scope.classes.indexOf('full-width') === -1) {
654+
scope.classes = scope.classes + ' full-width';
655+
} else if (newValue && scope.classes.indexOf('full-width') > -1) {
656+
scope.classes = scope.classes.split('full-width').join('');
657+
}
658+
}
659+
resetState(scope);
660+
initOptions(scope);
661+
}
662+
});
642663
scope.$watch('options.storage', function (storage) {
643664
if (storage) {
644665
if (!scope.options.storageKey) {
@@ -2182,7 +2203,7 @@ angular.module('apMesa.templates', [
21822203
angular.module('src/templates/apMesa.tpl.html', []).run([
21832204
'$templateCache',
21842205
function ($templateCache) {
2185-
$templateCache.put('src/templates/apMesa.tpl.html', '<div class="ap-mesa-wrapper" ng-class="{\n' + '\'paging-strategy-paginate\': options.pagingStrategy === \'PAGINATE\',\n' + '\'paging-strategy-scroll\': options.pagingStrategy === \'SCROLL\',\n' + '\'ap-mesa-loading-error\': !!transientState.loadingError,\n' + '\'ap-mesa-no-data\': !transientState.loading && !transientState.loadingError && visible_rows.length === 0\n' + '}">\n' + ' <table ng-class="classes" class="ap-mesa mesa-header-table">\n' + ' <thead>\n' + ' <!-- MAIN ROW OF COLUMN HEADERS -->\n' + ' <tr ui-sortable="sortableOptions" ng-model="enabledColumnObjects" class="ap-mesa-header-row">\n' + '\n' + ' <!-- COLUMN HEADERS -->\n' + ' <th\n' + ' scope="col"\n' + ' ng-repeat="column in enabledColumnObjects"\n' + ' ng-click="toggleSort($event,column)"\n' + ' ng-class="[\n' + ' {\n' + ' \'sortable-column\' : column.sort,\n' + ' \'select-column\': column.selector,\n' + ' \'is-sorting\': sortDirection[column.id]\n' + ' },\n' + ' \'table-header-\' + column.id,\n' + ' column.classes ? column.classes : \'\'\n' + ' ]"\n' + ' ng-attr-title="{{ column.title || \'\' }}"\n' + ' ng-style="{ width: column.width, \'min-width\': column.width, \'max-width\': column.width }">\n' + '\n' + ' <!-- COLUMN TEXT -->\n' + ' <span class="column-text">\n' + ' <input ng-if="column.selector" type="checkbox" ng-checked="isSelectedAll()" ng-click="toggleSelectAll($event)" />\n' + ' <span\n' + ' class="ap-mesa-sort-icon" \n' + ' ng-if="column.sort"\n' + ' title="This column is sortable. Click to toggle sort order. Hold shift while clicking multiple columns to stack sorting.">\n' + ' <span class="sorting-icon {{ getSortClass( sortDirection[column.id] ) }}"></span>\n' + ' <span ng-bind="transientState.sortPriority[column.id]" class="sort-priority" ng-if="transientState.sortPriorityShow && transientState.sortPriority[column.id]"></span>\n' + ' </span>\n' + ' <span class="ap-mesa-th-title" ap-mesa-th-title></span>\n' + ' </span>\n' + '\n' + ' <!-- COLUMN RESIZER -->\n' + ' <span\n' + ' ng-if="!column.lockWidth"\n' + ' class="column-resizer"\n' + ' ng-class="{\'discreet-width\': !!column.width}"\n' + ' title="Click and drag to set discreet width. Click once to clear discreet width."\n' + ' ng-mousedown="startColumnResize($event, column)">\n' + ' &nbsp;\n' + ' </span>\n' + '\n' + ' </th>\n' + ' </tr>\n' + '\n' + ' <!-- ROW OF COLUMMN FILTERS -->\n' + ' <tr ng-if="hasFilterFields() && transientState.showFiltersRow" class="ap-mesa-filter-row">\n' + '\n' + ' <!-- COLUMN FILTER CELLS -->\n' + ' <td ng-repeat="column in enabledColumnObjects" ng-class="\'column-\' + column.id">\n' + '\n' + ' <!-- FILTER INPUT -->\n' + ' <input\n' + ' type="text"\n' + ' ng-if="(column.filter)"\n' + ' ng-model="persistentState.searchTerms[column.id]"\n' + ' ng-attr-placeholder="{{ column.filterPlaceholder ? column.filterPlaceholder : (column.filter.placeholder || \'filter\') }}"\n' + ' ng-attr-title="{{ column.filter && column.filter.title }}"\n' + ' ng-class="{\'active\': persistentState.searchTerms[column.id] }">\n' + '\n' + ' <!-- FILTER CLEAR BUTTON -->\n' + ' <button\n' + ' ng-if="(column.filter)"\n' + ' ng-show="persistentState.searchTerms[column.id]"\n' + ' class="clear-search-btn"\n' + ' role="button"\n' + ' type="button"\n' + ' ng-click="clearAndFocusSearch(column.id)">\n' + ' &times;\n' + ' </button>\n' + '\n' + ' </td>\n' + ' </tr>\n' + ' </thead>\n' + ' </table>\n' + ' <div ap-mesa-status-display></div>\n' + ' <div class="mesa-rows-table-wrapper" ng-style="tbodyNgStyle" ng-hide="transientState.loadingError">\n' + ' <table ng-class="classes" class="ap-mesa mesa-rows-table">\n' + ' <thead>\n' + ' <th\n' + ' scope="col"\n' + ' ng-repeat="column in enabledColumnObjects"\n' + ' ng-style="{ width: column.width, \'min-width\': column.width, \'max-width\': column.width }"\n' + ' ></th>\n' + ' </tr>\n' + ' </thead>\n' + ' <tbody ng-if="options.pagingStrategy === \'SCROLL\'" ap-mesa-dummy-rows="[0,transientState.rowOffset]" cell-content="..."></tbody>\n' + ' <tbody ap-mesa-rows class="ap-mesa-rendered-rows"></tbody>\n' + ' <tbody ng-if="options.pagingStrategy === \'SCROLL\'" ap-mesa-dummy-rows="[transientState.rowOffset + visible_rows.length, transientState.filterCount]" cell-content="..."></tbody>\n' + ' </table>\n' + ' </div>\n' + ' <div class="ap-mesa-pagination" ng-if="options.pagingStrategy === \'PAGINATE\'" ap-mesa-pagination-ctrls></div>\n' + '</div>\n' + '');
2206+
$templateCache.put('src/templates/apMesa.tpl.html', '<div>\n' + ' <div class="ap-mesa-wrapper" ng-class="{\n' + ' \'paging-strategy-paginate\': options.pagingStrategy === \'PAGINATE\',\n' + ' \'paging-strategy-scroll\': options.pagingStrategy === \'SCROLL\',\n' + ' \'ap-mesa-loading-error\': !!transientState.loadingError,\n' + ' \'ap-mesa-no-data\': !transientState.loading && !transientState.loadingError && visible_rows.length === 0,\n' + ' \'ap-mesa-nonfluid\': options.fixedWidthLayout\n' + ' }">\n' + ' <table ng-class="classes" class="ap-mesa mesa-header-table">\n' + ' <thead>\n' + ' <!-- MAIN ROW OF COLUMN HEADERS -->\n' + ' <tr ui-sortable="sortableOptions" ng-model="enabledColumnObjects" class="ap-mesa-header-row">\n' + '\n' + ' <!-- COLUMN HEADERS -->\n' + ' <th\n' + ' scope="col"\n' + ' ng-repeat="column in enabledColumnObjects"\n' + ' ng-click="toggleSort($event,column)"\n' + ' ng-class="[\n' + ' {\n' + ' \'sortable-column\' : column.sort,\n' + ' \'select-column\': column.selector,\n' + ' \'is-sorting\': sortDirection[column.id]\n' + ' },\n' + ' \'table-header-\' + column.id,\n' + ' column.classes ? column.classes : \'\'\n' + ' ]"\n' + ' ng-attr-title="{{ column.title || \'\' }}"\n' + ' ng-style="{ width: options.fixedWidthLayout ? \'auto\' : column.width, \'min-width\': column.width, \'max-width\': column.width }">\n' + '\n' + ' <!-- COLUMN TEXT -->\n' + ' <span class="column-text">\n' + ' <input ng-if="column.selector" type="checkbox" ng-checked="isSelectedAll()" ng-click="toggleSelectAll($event)" />\n' + ' <span\n' + ' class="ap-mesa-sort-icon" \n' + ' ng-if="column.sort"\n' + ' title="This column is sortable. Click to toggle sort order. Hold shift while clicking multiple columns to stack sorting.">\n' + ' <span class="sorting-icon {{ getSortClass( sortDirection[column.id] ) }}"></span>\n' + ' <span ng-bind="transientState.sortPriority[column.id]" class="sort-priority" ng-if="transientState.sortPriorityShow && transientState.sortPriority[column.id]"></span>\n' + ' </span>\n' + ' <span class="ap-mesa-th-title" ap-mesa-th-title></span>\n' + ' </span>\n' + '\n' + ' <!-- COLUMN RESIZER -->\n' + ' <span\n' + ' ng-if="!column.lockWidth"\n' + ' class="column-resizer"\n' + ' ng-class="{\'discreet-width\': !!column.width}"\n' + ' title="Click and drag to set discreet width. Click once to clear discreet width."\n' + ' ng-mousedown="startColumnResize($event, column)">\n' + ' &nbsp;\n' + ' </span>\n' + '\n' + ' </th>\n' + ' </tr>\n' + '\n' + ' <!-- ROW OF COLUMMN FILTERS -->\n' + ' <tr ng-if="hasFilterFields() && transientState.showFiltersRow" class="ap-mesa-filter-row">\n' + '\n' + ' <!-- COLUMN FILTER CELLS -->\n' + ' <td ng-repeat="column in enabledColumnObjects" ng-class="\'column-\' + column.id">\n' + '\n' + ' <!-- FILTER INPUT -->\n' + ' <input\n' + ' type="text"\n' + ' ng-if="(column.filter)"\n' + ' ng-model="persistentState.searchTerms[column.id]"\n' + ' ng-attr-placeholder="{{ column.filterPlaceholder ? column.filterPlaceholder : (column.filter.placeholder || \'filter\') }}"\n' + ' ng-attr-title="{{ column.filter && column.filter.title }}"\n' + ' ng-class="{\'active\': persistentState.searchTerms[column.id] }"\n' + ' ng-style="{\'width\': options.fixedWidthLayout ? column.width : \'100%\'}">\n' + '\n' + ' <!-- FILTER CLEAR BUTTON -->\n' + ' <button\n' + ' ng-if="(column.filter)"\n' + ' ng-show="persistentState.searchTerms[column.id]"\n' + ' class="clear-search-btn"\n' + ' role="button"\n' + ' type="button"\n' + ' ng-click="clearAndFocusSearch(column.id)">\n' + ' &times;\n' + ' </button>\n' + '\n' + ' </td>\n' + ' </tr>\n' + ' </thead>\n' + ' </table>\n' + ' <div ap-mesa-status-display></div>\n' + ' <div class="mesa-rows-table-wrapper" ng-style="tbodyNgStyle" ng-hide="transientState.loadingError"\n' + ' ng-class="{\n' + ' \'fixed-width-layout\': options.fixedWidthLayout,\n' + ' \'auto-layout\': !options.fixedWidthLayout\n' + ' }">\n' + ' <table ng-class="classes" class="ap-mesa mesa-rows-table">\n' + ' <colgroup ng-if="options.fixedWidthLayout">\n' + ' <col ng-repeat="column in enabledColumnObjects"\n' + ' ng-style="{ width: column.width }"\n' + ' />\n' + ' </colgroup>\n' + ' <thead>\n' + ' <tr>\n' + ' <th\n' + ' scope="col"\n' + ' ng-repeat="column in enabledColumnObjects"\n' + ' ng-style="{ width: options.fixedWidthLayout ? \'auto\' : column.width, \'min-width\': column.width, \'max-width\': column.width }"\n' + ' ></th>\n' + ' </tr>\n' + ' </thead>\n' + ' <tbody ng-if="options.pagingStrategy === \'SCROLL\'" ap-mesa-dummy-rows="[0,transientState.rowOffset]" cell-content="..."></tbody>\n' + ' <tbody ap-mesa-rows class="ap-mesa-rendered-rows"></tbody>\n' + ' <tbody ng-if="options.pagingStrategy === \'SCROLL\'" ap-mesa-dummy-rows="[transientState.rowOffset + visible_rows.length, transientState.filterCount]" cell-content="..."></tbody>\n' + ' </table>\n' + ' </div>\n' + ' </div>\n' + ' <div class="ap-mesa-pagination" ng-if="options.pagingStrategy === \'PAGINATE\'" ap-mesa-pagination-ctrls></div>\n' + '</div>');
21862207
}
21872208
]);
21882209
angular.module('src/templates/apMesaDummyRows.tpl.html', []).run([

0 commit comments

Comments
 (0)