npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

ember-table-data

v0.0.0-beta.32

Published

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

Downloads

19

Readme

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.