ember-table-data

0.0.0-beta.32 • Public • Published

ember-table-data

npm version Ember Observer Score Build Status Code Climate

Description

This Ember Addon exposes an easily customizable table-data component. The component is mainly responsible for building a 'Query object' as of yet.

This addon is still a work in progress.

Installation

Like most ember addons, simply run ember install ember-table-data and you should be all set.

Docs

Table-data

The Table-data component serves as the main container of the component. It's used to wrap the pagination/page-size component in the same container that the table in itself resides (Will eventually contain filters too). It currently exposes 'pagination', 'pageSize' and 'table'.

Property Key Default Value Type Description
records null (required) [] or function This is the way to get the data. Either you pass 'records' as an array directly, and then it'll paginate it locally (not done yet) or you pass a function returning a promise that'll be called to get the data. A Query object is passed to the function, but you decide how you use it. If you've got any special case to do, usually you'd do it here.
Example
{{#table-data records=(action 'getData') as |tableData|}}
actions: {
    getData(queryObj, defaultSerializedObject){
      return this.get('store').query('data', queryObj);
    }
  }

The defaultSerializedObject is an object serialized for the C# API so that it can deserialize an array object for the filters (queryParams). The queryObj is provided if you want to serialize it differently. You can use the queryObj straight up if your API accepts JSON in queryParams.

Pagination

The pagination component is used to show the currently shown page and navigate to other pages.

Here are the parameters that are available.

Property Key Default Value Type Description
showFL true boolean Shows first/last pagination buttons
showPN true boolean Shows previous/next pagination buttons
showHasMore true boolean Shows ... if some pages aren't shown
nbPagesToShow 5 int Number of pages to show in pagination

Page size

The pageSize component is used to select the number of records to show per page.

Here are the parameters that are available.

Property Key Default Value Type Description
pageSize 10 int Selected (starting) page-size
pageSizes [5, 10, 15, 25, 50, 100] int array Page-size options

Filters

The 'filter' component is exposed if you want to have the filters visible. The filter component is used as a block component. It expose 3 component: 'header', 'body' and 'footer'.

Here are the parameters that are available.

Properties Default Value Type Description
properties Ember array array Represents the available properties to be able to filter
comparators see below the default comparators array Represents the comparator to override/add to the default comparators
removeInvalidFiltersOnUpdate false boolean Set to true to remove invalid filters from the filters when filtering. By default, invalid filters are kept, but filtered out before calling the records() method of table-data
We provide the filter-object in the utils. The filter-object contains 3 properties.
Properties Description
label Represents the label that will be show in the dropdown to select the property for filter
propertyType Represents the type of the property to filter comparators
valueForQuery Represents the value that will be used when we will construct the serialized object

Here an exemple of the properties array :

import filterObject from 'ember-table-data/utils/filter-object';
[...]
properties: computed('i18n.locale', function () {
    let array = A();
    array.pushObject(filterObject.create({
      label:'Label to be display in the dropdown',
      propertyType:'string',
      valueForQuery:'Label1'
    }));
    array.pushObject(filterObject.create({
      label:'Label 2 to be display in the dropdown',
      propertyType:'number',
      valueForQuery:'Label2'
    }));
    array.pushObject(filterObject.create({
      label:'Label 3 to be display in the dropdown',
      propertyType:'boolean',
      valueForQuery:'Label3.Code'
    }));
    array.pushObject(filterObject.create({
      label:'Label 4 to be display in the dropdown',
      propertyType:'date',
      valueForQuery:'Label4'
    }));
    return array;
  }),
Dropdown filters

For filter that require a dropdown (for a belongsTo relationships for example), you must provide additional properties.

Properties Default Value Type Description
data null array / function returning an array Represents options to show in the dropdown
labelPath 'label' string Represents the path of the label to show in the dropdown if data is an array of object
propertyPath 'id' string Represents the path of the property to select in the dropdown if data is an array of object

For example:

import filterObject from 'ember-table-data/utils/filter-object';
[...]
properties: computed('i18n.locale', function () {
    return [
      filterObject.create({
        labelPath:'other-label',
        propertyPath: 'other-id',
        propertyType:'dropdown',
        valueForQuery:'Label4'
      })
    ];
  }),
Comparators

We provide a default list of comparators for each type. When you want to add a comparator or override an existing one, you need to provide a list of comparator, using the comparator-object available in the utils.

Properties Description
label Represent the label that will be show in the dropdown to select the comparator for filter
internalName Represents the unique name of the comparator for a specific type (uniqueness is based on internalName + propertyType)
propertyType Represents the type of the property
valueForQuery Represents the value used when constructing the serialized object

Here the available default comparators :

import ComparatorObject from 'ember-table-data/utils/comparator-object';
[...]
A([
  ComparatorObject.create({label: 'Contains', internalName: 'contains', propertyType: 'string', valueForQuery:'{0}.Contains("{1}")'}),
  ComparatorObject.create({label: 'Ends with', internalName: 'endsWith', propertyType: 'string', valueForQuery:'{0}.EndsWith("{1}")'}),
  ComparatorObject.create({label: 'Equal', internalName: 'equal', propertyType: 'string', valueForQuery:'{0} == "{1}"'}),
  ComparatorObject.create({label: 'Not contains', internalName: 'notContains', propertyType: 'string', valueForQuery:'!({0}.Contains("{1}"))'}),
  ComparatorObject.create({label: 'Not ends with', internalName: 'notEndsWith', propertyType: 'string', valueForQuery:'!({0}.EndsWith("{1}"))'}),
  ComparatorObject.create({label: 'Not equal', internalName: 'notEqual', propertyType: 'string', valueForQuery:'{0} != "{1}"'}),
  ComparatorObject.create({label: 'Not starts with', internalName: 'notStartsWith', propertyType: 'string', valueForQuery:'!({0}.StartsWith("{1}"))'}),
  ComparatorObject.create({label: 'Starts with', internalName: 'startsWith', propertyType: 'string', valueForQuery:'{0}.StartsWith("{1}")'}),

  ComparatorObject.create({label: '<>', internalName: 'notEqual', propertyType: 'number', valueForQuery:'{0} != {1}'}),
  ComparatorObject.create({label: '<', internalName: 'lessThan', propertyType: 'number', valueForQuery:'{0} < {1}'}),
  ComparatorObject.create({label: '<=', internalName: 'lessThanOrEqual', propertyType: 'number', valueForQuery:'{0} <= {1}'}),
  ComparatorObject.create({label: '=', internalName: 'equal', propertyType: 'number', valueForQuery:'{0} == {1}'}),
  ComparatorObject.create({label: '>', internalName: 'greaterThan', propertyType: 'number', valueForQuery:'{0} > {1}'}),
  ComparatorObject.create({label: '>=', internalName: 'greaterThanOrEqual', propertyType: 'number', valueForQuery:'{0} >= {1}'}),

  ComparatorObject.create({label: '<>', internalName: 'notEqual', propertyType: 'date', valueForQuery:'{0} != {1}'}),
  ComparatorObject.create({label: '<', internalName: 'lessThan', propertyType: 'date', valueForQuery:'{0} < {1}'}),
  ComparatorObject.create({label: '<=', internalName: 'lessThanOrEqual', propertyType: 'date', valueForQuery:'{0} <= {1}'}),
  ComparatorObject.create({label: '=', internalName: 'equal', propertyType: 'date', valueForQuery:'{0} == {1}'}),
  ComparatorObject.create({label: '>', internalName: 'greaterThan', propertyType: 'date', valueForQuery:'{0} > {1}'}),
  ComparatorObject.create({label: '>=', internalName: 'greaterThanOrEqual', propertyType: 'date', valueForQuery:'{0} >= {1}'}),

  ComparatorObject.create({label: '<>', internalName: 'notEqual', propertyType: 'boolean', valueForQuery:'{0} != {1}'}),
  ComparatorObject.create({label: '=', internalName: 'equal', propertyType: 'boolean', valueForQuery:'{0} == {1}'})
]);
Override a comparator

If you provide a list of comparators in the filters, we will match the internalName and the type. If you provide a label and/or a valueForQuery, we will override the default one with the new value.

If you use a globalization system, do not forget to make a computed that watches the locale for your new comparators to have the label change when changing language.

{{#tableData.filter properties=properties comparators=userComparators as |filter|}}
Header

The 'header' component exposed in the filter component is used to display the "Add row" button. The addButton will be generated as a button. The click function will add 1 row to the filter list. It is provided so that you can style/place it properly.

{{#filter.header as |header|}}
  {{#header.addButton }}
    Can be block component or not.
  {{/header.addButton}}
{{/filter.header}}
Body / Row

The 'body' and 'row' component expose the 'property', 'comparator', 'value' and 'deleteButton' component. The 'property' component is used to display the property dropdown to filter on. The 'comparator' component is used to display the comparator list base on the type of the property selected. The 'value' component is used to display an input to enter the value on which to filter. The 'deleteButton' is used to display a button that will delete the row from the filters. This component renders with button tag.

The 'row' component exposes the count of the filters. You can use that to have logical display on the deleteButton component. In the case below, we display the delete button only if 2 filter or more are in the list.

{{#filter.body as |body|}}
  {{#body.row as |row|}}
    {{row.property }}
    {{row.comparator }}
    {{row.value }}
    {{#if (gt row.count 1)}}
      {{#row.deleteButton }}
        You can add Text or Icon here for the delete button.
      {{/row.deleteButton}}
    {{/if}}
  {{/body.row}}
{{/filter.body}}
Override input value control

You can override or create input value for current or custom propertyType. The component will search in the components/filter-input/PROPERTYTYPE. We provide default inputs for each type. The string type will generate an input of type text. The number type will generate an input of type number. The date type will generate an input of type date. The boolean type will generate an input of type boolean.

When you override an input value, you need to execute the provided action when the value changes. The component receives a closure action named 'valueChange' that needs to be executed when the value is changed to update the filter object. The action receives the value as a parameter. So when the value is changed, you need to call the action. See the example below.

{
[...]
this.get('valueChange')("THE NEW VALUE");
}

If you want the override or add a component, you can use the ember cli command : ember g component filter-input/PROPERTYTYPE. Do not forget to provide the appropriate comparator if you use a custom 'propertyType'.

Footer

The 'footer' component exposes the 'filterButton' and the 'clearButton'. The 'filterButton' will trigger the getData action to send the call with the new queryObj. It will also remove all invalid filters from the list. The invalid filters are the filters that the comparator, value or property are not defined/selected. The 'clearButton' will clear the filter list and trigger the getData action with the new queryObj.

{{#filter.footer as |footer| }}
  {{#footer.filterButton}}
    Can be text or icon.
  {{/footer.filterButton}}
  {{#footer.clearButton }}
    Can be text or icon.
  {{/footer.clearButton}}
{{/filter.footer}}

Table

The table component is the main component of the table-data. It's used to show to table in itself. It exposes 'header' and 'body'.

Header

The header component is the equivalent of tHead, it wraps the header. It exposes 'row'.

Body

The body component is the equivalent of tBody, it wraps all the records. It exposes 'row', 'loadingRow', 'emptyRow' and record.

Here, loadingRow and emptyRow are 'row' components that are shown when either the records are loading or when there's no records to be shown.

Row

The 'row' component (both from header and body) is simply a table row (tr).

Property Key Default Value Type
colspan 1 int
Cell

The 'cell' component (both from header and body) is simply a table cell (td).

Example

Here's what a complete table-data would look like:

{{#table-data records=records as |tableData|}}
  {{#tableData.filter properties=properties  as |filter|}}
    {{#filter.header as |header|}}
      {{#header.addButton }}
        Can be block component or not.
      {{/header.addButton}}
    {{/filter.header}}

    {{#filter.body as |body|}}
      {{#body.row as |row|}}
        {{row.property }}
        {{row.comparator }}
        {{row.value }}
        {{#if (gt row.count 1)}}
          {{#row.deleteButton}}
            can be block component or not.
          {{/row.deleteButton}}
        {{/if}}
      {{/body.row}}
    {{/filter.body}}

    {{#filter.footer as |footer| }}
          {{#footer.filterButton }}
            Can be block component or not.
          {{/footer.filterButton}}
          {{#footer.clearButton }}
            Can be block component or not.
          {{/footer.clearButton}}
    {{/filter.footer}}
  {{/tableData.filter}}

  <div class="row">
    {{tableData.pageSize class="col-2"}}
    {{tableData.pagination class="col-6"}}
  </div>

  {{#tableData.table class="table-striped col-12" as |table|}}
    {{#table.header as |header|}}
      {{#header.row as |row|}}
        {{#row.cell}}
          First cell
        {{/row.cell}}
        {{#row.cell}}
          Second cell
        {{/row.cell}}
        {{#row.cell}}
          Third cell
        {{/row.cell}}
      {{/header.row}}
    {{/table.header}}

    {{#table.body as |body record|}}

      {{#body.row as |row|}}
        {{#row.cell}}
          c1 {{record}}
        {{/row.cell}}
        {{#row.cell}}
          c2 {{record}}
        {{/row.cell}}
        {{#row.cell}}
          c3 {{record}}
        {{/row.cell}}
      {{/body.row}}

      {{#body.emptyRow as |row|}}
        {{#row.cell colspan=3}}
          No records
        {{/row.cell}}
      {{/body.emptyRow}}

      {{#body.loadingRow as |row|}}
        {{#row.cell colspan=3}}
          Loading records
        {{/row.cell}}
      {{/body.loadingRow}}

    {{/table.body}}
  {{/tableData.table}}
{{/table-data}}

For more information on using ember-cli, visit https://ember-cli.com/.

License

This project is licensed under the MIT License.

Package Sidebar

Install

npm i ember-table-data

Weekly Downloads

43

Version

0.0.0-beta.32

License

MIT

Unpacked Size

70.3 kB

Total Files

97

Last publish

Collaborators

  • oreoz
  • shadowere
  • mechabear
  • marcus_91
  • alanlalonde
  • piknik