diff --git a/addon/components/models-table-server-paginated.js b/addon/components/models-table-server-paginated.js index 5733173e..b76bd06b 100644 --- a/addon/components/models-table-server-paginated.js +++ b/addon/components/models-table-server-paginated.js @@ -134,6 +134,48 @@ export default ModelsTable.extend({ return Math.min(pageMax, itemsCount); }), + _buildColumnMap() { + const attrs = this.get('data.type.attributes'); + let columnMap = {}; + + if (Ember.typeOf(attrs) !== 'undefined') { + attrs.forEach(attr => { + columnMap[attr.name] = this._buildColumn(attr); + }); + } + + return columnMap; + }, + + /** + * Builds a column configuration from a model's attributes. + * Used to create configurations for ```this.defaultColumns``` and overrides the default method + * to enable configuration of a model-table's propertyName through model.attr options. + * + * @param modelAttr + * @returns {{propertyName}} + * @private + */ + _buildColumn(modelAttr) { + const data = this.get('data'); + const options = Ember.get(modelAttr, 'options'); + let colOptions = { + propertyName: modelAttr.name + }; + + if (data.get(`query.${modelAttr.name}`)) { + colOptions.filterString = data.get(`query.${modelAttr.name}`); + } + + if (modelAttr && options) { + if (options.cellTemplate) { + colOptions.template = cellTemplate; + } + } + + return colOptions; + }, + /** * This function actually loads the data from the server. * It takes the store, modelName and query from the passed in data-object and adds page, sorting & filtering to it. @@ -169,11 +211,17 @@ export default ModelsTable.extend({ } // Add global filter - let globalFilter = get(this, 'filterQueryParameters.globalFilter'); + const filterParam = get(this, 'filterQueryParameters.globalFilter'); + let searchableItems = this.get('visibleProcessedColumns') || []; + if (this.get('doFilteringByHiddenColumns')) { + searchableItems = this.get('columns') || []; + } if (filterString) { - query[globalFilter] = filterString; + query[filterParam] = filterString; + query[filterParam+'Keys'] = searchableItems.map(col=>{ return col.propertyName }); } else { - delete query[globalFilter]; + delete query[filterParam]; + delete query[filterParam+'Keys']; } // Add per-column filter diff --git a/addon/components/models-table.js b/addon/components/models-table.js index 0855bb17..a0b9ea51 100644 --- a/addon/components/models-table.js +++ b/addon/components/models-table.js @@ -303,7 +303,102 @@ export default Component.extend({ * @name ModelsTable#columns * @default [] */ - columns: A([]), + // columns: A([]), + + // defaultColumns is an array of propertyNames (string or object) where order will + // dictate the order displayed. If a bad '' or {propertyName:'value'} + // is given, it is skipped and a warning will display in the browser's developer console. + // If no defaultColumns are given, all table columns will be shown. + // + // Examples: + // array of property names (['id', 'createdAt', 'moreStuff']) that each match a column. + // - or - + // array of ember-model-table "columns" (http://onechiporenko.github.io/ember-models-table/) + // {propertyName:'id', title: 'my cool title', template: 'component/data-table/cell-template'}} + defaultColumns: A([]), + + // Columns is required by the ember-models-table component. DataTable will auto create columns + // based on 'this.data' and the this.defaultColumns array. If this behavior is not desired, + // overriding this property is allowed. + columns: computed('data', 'defaultColumns', { + get() { + let columns = []; + let usedNames = []; + let columnMap = this._buildColumnMap(); + const defaultColumns = this.get('defaultColumns') || []; + + defaultColumns.forEach(col => { + // col objects merge col and ```columnMap[col] || {}```; + // the object should follow ember-models-data column definition. + if (Ember.typeOf(col) == 'string') { + if (columnMap[col]) { + columns.push(columnMap[col]); + usedNames.push(col); + } else { + Ember.warn(`No propertyName found for ${col}`, false, {id: 'data-table.columns-builder'}); + } + } else { + if (columnMap[col.propertyName]) { + let d = Ember.copy(columnMap[col.propertyName]); + columns.push(Ember.merge(d, col)); + usedNames.push(col.propertyName); + } else { + Ember.warn(`No propertyName found for ${col.propertyName}`, false, {id: 'data-table.columns-builder'}); + } + } + }); + + // remove used properties so they aren't double inserted. + usedNames.forEach(n => { delete columnMap[n] }); + + // initialColumns should be a list of strings that correspond to propertyNames. + Object.keys(columnMap).forEach(col => { + if (defaultColumns.length > 0) { + columnMap[col].isHidden = true; + } + columns.push(columnMap[col]); + }); + + return A(columns); + } + }), + + _buildColumnMap(){ + let columnMap = {}; + const data = this.get('data') || []; + if (!Ember.isEmpty(data)) { + Object.keys(this.get('data')[0]).forEach(attr => { + columnMap[attr] = this._buildColumn(attr); + }); + } + return columnMap; + }, + + /** + * takes a model at + * @param attr + * @returns {{propertyName}} + * @private + */ + _buildColumn(attr) { + const data = this.get('data'); + const options = Ember.get(attr, 'options'); + let colOptions = { + propertyName: attr + }; + + if (data.get(`query.${attr.name}`)) { + colOptions.filterString = data.get(`query.${attr.name}`); + } + + if (attr && options) { + if (options.template) { + colOptions.template = template; + } + } + + return colOptions; + }, /** * @type {Ember.Object[]} diff --git a/package.json b/package.json index 39b3c3c9..4a485e2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ember-models-table", - "version": "1.11.0-beta.2", + "version": "100.0.1", "description": "Table with pagination, sorting and filtering", "keywords": [ "ember-addon" diff --git a/tests/dummy/app/router.js b/tests/dummy/app/router.js index 07df02a8..b198d9e9 100644 --- a/tests/dummy/app/router.js +++ b/tests/dummy/app/router.js @@ -23,6 +23,7 @@ export default Router.map(function() { this.route('add-remove-column'); this.route('grouped-headers'); this.route('server-table'); + this.route('server-table-default-columns'); this.route('route-cells'); this.route('expandable-rows'); this.route('display-data-changed-action'); diff --git a/tests/dummy/app/routes/examples/server-table-default-columns.js b/tests/dummy/app/routes/examples/server-table-default-columns.js new file mode 100644 index 00000000..5875b51f --- /dev/null +++ b/tests/dummy/app/routes/examples/server-table-default-columns.js @@ -0,0 +1,23 @@ +import Ember from 'ember'; +import generateContent from '../../utils/c'; + +export default Ember.Route.extend({ + + model() { + return this.get('store').query('user', {}); + }, + + setupController(controller) { + + controller.set('otherData', generateContent(10)); + controller.set('defaultColumns', [ + //id + 'index', + 'firstName', + {propertyName: 'lastName', title: 'Family Name', className: 'text-success'}, + ]); + + return this._super(...arguments); + } + +}); diff --git a/tests/dummy/app/templates/examples/server-table-default-columns.hbs b/tests/dummy/app/templates/examples/server-table-default-columns.hbs new file mode 100644 index 00000000..69379ba5 --- /dev/null +++ b/tests/dummy/app/templates/examples/server-table-default-columns.hbs @@ -0,0 +1,24 @@ +
+
+

`models-table-server-paginated` example

+

Component is extended into the `my-server-table` (see tests/dummy/app/components/my-server-table.js)

+

Another way to setup your table is to provide the default

+
+
+ {{! models-table data=otherData defaultColumns=defaultColumns}} + {{my-server-table data=model defaultColumns=defaultColumns}} +
+
+

Component usage:

+
\{{my-server-table
+data=model defaultColumns=defaultColumns}}
+

defaultPropertyNames:

+
{{to-string this 'defaultColumns'}}
+ +

model:

+
{{to-string this 'model.toJSON()'}}
+ +

data:

+
{{to-string this 'otherData'}}
+
+
\ No newline at end of file