GithubHelp home page GithubHelp logo

adopted-ember-addons / ember-light-table Goto Github PK

View Code? Open in Web Editor NEW
311.0 18.0 129.0 16.75 MB

Lightweight, contextual component based table for Ember

Home Page: http://adopted-ember-addons.github.io/ember-light-table/

License: MIT License

JavaScript 76.33% HTML 1.02% CSS 1.03% Handlebars 18.37% SCSS 3.25%
ember ember-addon table responsive infinite-scroll

ember-light-table's Issues

Improve Documentation

  • Annotate each available component property with a helpful description and maybe an example where possible
  • Cell Type and Column Type --> What they are and how they can be used (including their appropriate blueprint generators) #91
  • Add overall examples in module homes
  • Maybe rename the modules to make everything easier to read? I feel like the docs right now are really hard to follow IMHO

Reorder columns

Just wondering if there's any interest in draggable column headings for column re-ordering. This is the one feature missing that is stopping us dropping this in.

Has it been looked at previously? Would you consider a PR for it?

Two header rows and no data rows

I'm using the code as described in the docs and:

  • I can't get data rows to show up (i.e. the body)
  • Both the {{t.head}} and {{t.foot}} repeat the same header row

extra info:

  • calling light-table inside {{posts-table model=model.user.posts}}
  • using ember v2.5.1 & ember-data v2.6.0

Support options hash when invoking row-related methods like Table.addRow()

Currently, when invoking row-related methods like Table.addRow(), the options hash doesn't make it to the Row constructor:

this.set('table', new Table(columns = [], rows = []));

this.get('table').addRow({
  key: 'value'
}, {
  classNames: 'some-class-name'
});

// class name is not set on the row

To get the options to be set on a row, you currently have to initialize a Row first.

let row = new Row({
  key: 'value'
}, {
  classNames: 'some-class-name'
});

this.get('table').addRow(row);

Would it not be great if you could pass along the options along with the data when using methods like addRow or pushRow?

Style Table Element

Hi, i'm trying to style the table element with bootstrap like this. I added the classNames attribute in the component template but it adds the classes to the div, not the table tag.
{{#light-table table classNames='table table-bordered table-hover table-condensed' as |t|}}
Is this supported? am i doing something wrong?

ember-light-table: 1.0.0
ember-cli: 2.6.2
node: 6.2.2
os: linux x64

Row component binding

Is there a concept to bind a different row component? I want to create different tables with different row components (one row component per table).

The Text within the row should be highlighted by classbinding.

Is there a different solution to realize this?

Performance problems

Hi again,

I've noticed a performance problem and I haven't figured out what is causing it yet. I tried attaching the profile but github doesn't allow .cpuprofiles. You can easily reproduce it by profiling the demo table at http://offirgolan.github.io/ember-light-table/#/. The rendering speed isn't that noticeable since you're only rendering ~20 rows off the bat but even at ~150 rows, rendering speed is at ~2.5 seconds. I've reduced my table down to one row and have noticed in the profile that the one row creates about 3 large spikes that have a huge number of function calls. You can see spike after spike, for each row, if you profile the demo page.

I'm continuing to investigate. We really like ember-light-table but this performance issue is a show-stopper at the moment. Cheers,

Zach

Add css selectors for lines and cells

It can be useful to add css selectors to help to find a row or a cell. The row can have this #model-1.model and a row can be found with .attr. So, to find a cell, I can do something like $('#user-1 .name') to find the cell. It would be easier for styling and acceptance testing.

If we use EmberData, I think row.content.constuctor.name and row.content.id is enough to find the row id but I'm not sure for non-EmberData resources.

What you think?

Problems with cellComponent

I've encountered several issues trying to use the cellComponent property on my column definition. The docs don't make it clear that the component path must be light-table/cells/my-component.

If I provide a valuePath in the columns spec I get an error Cannot set read-only property "value" on object. The workaround is to define value: null on the Cell subclass, but the valuePath has no effect.

Also, the only way for me to get the value was from row.content.

Finally, my test file causes an error form ESLint TypeError: Cannot assign to read only property 'stack' of object '[object Object]'.

I'm using Ember 2.6.2 and Ember Data 2.6.1.

Access table object from column header component

I want to create a table that has a checkbox in the first column for selecting/deselecting each row. This works fine since the lt-row component passes row object to the cell component.

However, I also need to have a checkbox in the header that selects/deselects all rows in the table. But for this I need to have access to the table object and all rows in it. The biggest problem is that the header checkbox should be updated as the rows are being selected by the user, e.g., if the user selects all rows in the table one by one, the header checkbox should also be checked.

There doesn't seem to be a way to know what rows are selected in the table from the header component. As a workaround, I am passing the table object inside the tableActions parameter, but I hope there is a better way for doing this.

This is my checkbox-header component:

// components/checkbox-header.js
export default Ember.Component.extend({
    tagName: 'i',
    classNameBindings: ['icon'],

    iconChecked: 'fa fa-check-square-o',
    iconUnchecked: 'fa fa-square-o',

    table: Ember.computed.alias('tableActions.table'),
    notSelectedRows: Ember.computed.filterBy('table.rows', 'selected', false),
    allSelected: Ember.computed.empty('notSelectedRows'),

    icon: Ember.computed('allSelected', function() {
        return this.get('allSelected') ? this.get('iconChecked') : this.get('iconUnchecked');
    }),

    click() {
        this.get('table.rows').setEach('selected', !this.get('allSelected'));
    }
});

Table cut with columns > screen width

When the columns of the table are all set up with a fixed width and the sum of them is bigger than the screen width size, the table becomes scrollable on the x axis but the hidden content (the content of the columns that are out of the visible part of the table) is not rendered when scrolling on it.

Sorting

Is sorting implemented by default? Seems like {{t.head}} has sort enabled by default, but nothing seems to happen. Here's my setup:

{{#light-table table class='table table-striped table-hover' as |t|}}
  {{t.head multiColumnSort=true}}
  {{t.body onRowClick=(action 'onclick')}}
{{/light-table}}

Looking at the demo app, it looks like you implement sorting yourself by sending the params to the server..

onScrolledToBottom called just once.

Thank you for sharing your addon.
In my implementation, which is basically a copy of the example at http://offirgolan.github.io/ember-light-table/, "onScrolledToBottom" is called just once when the component first loads, but it doesn't get called again on scroll (although "canLoadMore" is true after the first fetch of records).
Are there any more configurations needed for the infinite scroll to work?
I didn't see any in the example or docs.
Thank you very much!

Show multiple model fields in one column

Is there a way to show multiple model fields in one column? I don't want to use grouped columns but would rather show multiple model fields stacked in one column for each table row.

Add a "hideable" option to configure if column can be hidden

The Column class has the sortable option to configure if it can be sorted or not. It would be nice to also have an option to configure if the column can be hidden or not.

Having this option in the Column class will be useful to create a generic component for the user to choose the columns visible in the table, something like a list with a checkbox for each column in the table that can be hidden.

Add-on 'ember-in-viewport' uses deprecated Ember.merge

When using onScrolledToBottom for infinite scrolling, the ember-in-viewport add-on is used which defines an isInViewport function containing the line:

const tolerances = merge(defaultTolerance, tolerance);

This is causing the following deprecation warning to flood the console:

DEPRECATION: Usage of Ember.merge is deprecated, use Ember.assign instead. [deprecation id: ember-metal.merge] See http://emberjs.com/deprecations/v2.x/#toc_ember-merge for more details.

Either another method of determining whether or not the component is in the viewport needs to be implemented or the add-on itself should be updated to use Ember.assign. I believe the usage of Ember.merge was deprecated in Ember 2.5 but I am not positive.

Add special value in valuePath to return the model it self.

I want to use a component to have actions buttons. For the moment, I can pass the id to retrieve the model but it can be useful to have something like this :

  columns: [
    {
      label: 'Actions',
      valuePath: 'self',
      sortable: false,
      cellComponent: 'kh-actions'
    }
  ]

What you think?

Need to bubble an action up to route/controller from a column's cellComponent...

...how does one do this? I've tried passing the action through the component, like so:

  {{#light-table table
    pickupTimeUpdated="pickupTimeUpdated"
    onScrolledToBottom=(action 'onScrolledToBottom')
    class="ui very basic table"
    scrollContainer='.table-scroll-container'
    as |t|
  }}

Nothing. I flailed and tried defining my action like onScrolledToBottom, too.

How'd I go about this?

Doesnt know how to instantiate this addon!

Sorry to say that the documentation is not giving any idea how to use this in real project.

after installing the addon, i generate a custom component 'inventory-table'

put the template in some index.hbs

// inventory/index.hbs
 {{#light-table table onScrolledToBottom=(action 'onScrolledToBottom') as |t|}}
     {{t.head
       onColumnClick=(action 'onColumnClick')
       iconAscending='fa fa-sort-asc'
       iconDescending='fa fa-sort-desc'
       fixed=true
     }}

     {{#t.body canSelect=false height='64vh' as |body|}}
       {{#if isLoading}}
         {{#body.loader}}
           {{table-loader}}
         {{/body.loader}}
       {{/if}}
     {{/t.body}}
   {{/light-table}}

pasted this content in the newly created component

//app/components/inventory-table.js
import Ember from 'ember';
import Table from 'ember-light-table';

const { isEmpty } = Ember;

export default Ember.Component.extend({
  page: 1,
  limit: 20,
  dir: 'asc',
  sort: null,
  table: null,
  isLoading: false,
  canLoadMore: true,

  columns: [{
    label: 'Avatar',
    valuePath: 'avatar',
    width: '60px',
    sortable: false,
    cellComponent: 'user-avatar'
  }, {
    label: 'First Name',
    valuePath: 'firstName',
    width: '150px'
  }, {
    label: 'Last Name',
    valuePath: 'lastName',
    width: '150px'
  }, {
    label: 'Address',
    valuePath: 'address'
  }, {
    label: 'State',
    valuePath: 'state'
  }, {
    label: 'Country',
    valuePath: 'country'
  }],

  init() {
    this._super(...arguments);
    this.set('table', new Table(this.columns));
  },

  fetchRecords() {
    this.set('isLoading', true);
    this.get('store').query('user', this.getProperties(['page', 'limit', 'sort', 'dir'])).then(records => {
      this.table.addRows(records);
      this.set('isLoading', false);
      this.set('canLoadMore', !isEmpty(records));
    });
  },

  actions: {
    onScrolledToBottom() {
      if(this.get('canLoadMore')) {
        this.incrementProperty('page');
        this.fetchRecords();
      }
    },

    onColumnClick(column) {
      if (column.sorted) {
        this.setProperties({
          dir: column.ascending ? 'asc' : 'desc',
          sort: column.get('valuePath'),
          page: 1
        });
        this.table.setRows([]);
        this.fetchRecords();
      }
    }
  }
});

initially it thrown

ember.debug.js:16628Uncaught Error: An action named 'onScrolledToBottom' was not found in <zahid-staging@controller:dashboard/inventory/index::ember930>.

The i removed this function from component helper

but dont know where to put the instantiation code

import Table from 'ember-light-table';
const table = new Table(columns, rows);

Tried in index controller , inventory-table.js(component file) , but it throws

ember.debug.js:16628Uncaught Error: Assertion Failed: [ember-light-table] table must be an instance of Table

May i get a clear picture of where to put these codes and how? I love this addon, but couldn't figure out how to use. please help

table-layout: auto

First off, I love Ember Light Table! Much easier than manually creating tables.

I'd like my table to behave like it has the CSS attribute "table-layout: auto". In other words, column widths change to accommodate the width of their contents. But since Ember Light Table renders the table head as a separate table, "table-layout: auto" doesn't consider the width of the body data below.

For example, look at the "League" column (4th from the left). It's wider than the column since Ember Light Table makes all the columns the same width:
screen shot 2016-07-16 at 8 45 26 pm

When I give the head and body tables the "table-layout: auto" attribute, the columns become misaligned:
screen shot 2016-07-16 at 8 49 51 pm

Scrollable Container and preventing db queries

Any thoughts on providing a hook for users to prevent calling the onScrolledToBottom method if they have already retrieved all their records from the db, or should this behavior be left up to the user?

height or max-height for the table height?

max-height allows the table to get reduced if the rows don't fill the specified height. I don't know if someone would be interested on having their tables filling always the same height independently of the number of rows. Maybe would be interesting to have both options?

Resizeable Columns

Is there a way to drag and expand the size of a column? For example if the text of the column is too large to be seen?

Cheers~

Multiselect

I've been reading through the docs and couldn't see any mention of how you might implement mutliselect?

I assume it's by adding selected rows to an array, but I'm not sure how to pass that back as a comparison for the table to keep track of which rows are selected..

I know it's designed for maximum flexibility for people to implement this sort of thing however best suits their app, but would it be possible to get a snippet as an example of how someone else has done it?

deprecation warning in tests

DEPRECATION: You modified (or sharedOptions.fixedHeader sharedOptions.fixedFooter) twice in a single render. This was unreliable in Ember 1.x and will be removed in Ember 3.0 [deprecation id: ember-views.render-double-modify]
        at logDeprecationStackTrace (http://localhost:7357/assets/vendor.js:16449:19)
        at HANDLERS.(anonymous function) (http://localhost:7357/assets/vendor.js:16556:7)
        at raiseOnDeprecation (http://localhost:7357/assets/vendor.js:16479:12)
        at HANDLERS.(anonymous function) (http://localhost:7357/assets/vendor.js:16556:7)
        at invoke (http://localhost:7357/assets/vendor.js:16572:7)
        at deprecate (http://localhost:7357/assets/vendor.js:16540:32)
        at Object.deprecate (http://localhost:7357/assets/vendor.js:25882:37)
        at Class.exports.default._emberMetalMixin.Mixin.create._Mixin$create.scheduleRevalidate (http://localhost:7357/assets/vendor.js:52825:26)
        at http://localhost:7357/assets/vendor.js:23046:32

height:auto

For some reason, when I set height to auto, the .tse-scroll-content div still has a manually set 300px height, so the table does not size itself to full height.

[RFC] Allow to at row at specific index and let it return itself afterwards

I came across a use-case where I needed to add a row to the beginning of the array. I've solved it by doing:

let row = Table.createRow(attribute);
this.get('table.rows').insertAt(0, row);

It may be a good idea to make a proper public API to do this. I was thinking about this.get('table').addRowAt(0, someObject). Or maybe change the argument signature of the addRow method by adding idx at the end, so you could do addRow(object, 0).

As a side note, it might also be a good idea to return the created Row after calling addRow. This way you can manipulate selected and expanded directly after you've added it.

Thoughts?

Ability to add row loop index as column

I'd like to have a first column that just adds an index to each row signifying the order models were taken from the database

equivalent to index in the following code snippet:

{{#each users as |user index|}}
  <tr>
    <td>{{index}}</td>
    <td>{{user.name}}</td>
    ...
  </tr>
{{/each}}

I couldn't pick up from the docs wether this was currently possible or not

Problems specifying the cellComponent

The docs don't make it clear that the component path must be light-table/cells/my-component.

If I provide a valuePath in the columns spec I get an error Cannot set read-only property "value" on object. The workaround is to define value: null on the Cell subclass, but the valuePath has no effect.

Also, the only way for me to get the value was from row.content.

'Undefined length' error caused by ember-composible?

I just pulled down beta5 to see whats new, and I'm getting this error:

Cannot read property 'length' of undefined
TypeError: Cannot read property 'length' of undefined
    at CoreObject.module.exports.filterHelpers (/my-project/node_modules/ember-light-table/node_modules/ember-composable-helpers/index.js:40:18)

Doing a quick search through the repo, I'm not sure what this sub-module is being used for in ember-light-table? There doesn't appear to be any addon configuration including the whitelist it appears to be looking for https://github.com/DockYard/ember-composable-helpers#configuration ?

isLoading

In the docs you have an isLoading option in the template examples, does that come from this addon or is that something we implement ourself?

If it's from the addon, where does it come from?

init functionality within light-table

Hey all,

I was curious why the init functionality, like creating a new Table and such isn't handled within the light-table component? As a result, I'm creating a wrapper table that all it does is exactly that and it adds one more, seemingly unnecessary, level of indentation in the hbs file likeso:

{{#netuitive-table-new
       model=model
       as |table|
}}
            {{#light-table table as |t|}}
              {{t.head}}

              {{#t.body as |body|}}
                {{#body.expanded-row as |row|}}
                  Hello <b>{{row.name}}!!</b>
                {{/body.expanded-row}}

                {{#if isLoading}}
                  {{#body.loader}}
                    Loading...
                  {{/body.loader}}
                {{/if}}

                {{#if table.isEmpty}}
                  {{#body.no-data}}
                    No users found.
                  {{/body.no-data}}
                {{/if}}
              {{/t.body}}

              {{t.foot}}
            {{/light-table}}
{{/netuitive-table-new}}
//netuitibe-table-new/component.js
import Ember from 'ember';
import Table from 'ember-light-table';

const computed = Ember.computed;

export default Ember.Component.extend({
  model: null,
  table: null,

  columns: [],

  init() {
    this._super(...arguments);
    this.set('table', new Table(this.get('columns'), this.get('model')));
  }
});
{{!-- /netuitive-table-new/template.hbs --}}
{{yield table}}

Infinite scroll fails when scrolling fast

When scrolling quite fast I've noticed the following behaviour:

  1. Scrolling starts and triggers the scroll handler which doesn't pass
  2. Scrolling finishes before the throttle timeout
  3. No more triggers are fired, no page is loaded unless you scroll back up

I've implemented a quick fix in our app by adding a debounce as well so that we always get a scroll trigger once scrolling stops but there may be a more efficient solution.

import Ember from 'ember';
import LightTable from 'ember-light-table/components/light-table';

const {$, run} = Ember;

export default LightTable.extend({
    _setupScrollEvents() {
        $(this.get('touchMoveContainer')).on('touchmove.light-table', run.bind(this, this._scrollHandler, '_touchmoveTimer'));
        $(this.get('scrollContainer')).on('scroll.light-table', run.bind(this, this._scrollHandler, '_scrollTimer'));
        $(this.get('scrollContainer')).on('scroll.light-table', run.bind(this, this._scrollHandler, '_scrollDebounce'));
    },

    _scrollHandler(timer) {
        this.set(timer, run.debounce(this, this._onScroll, 100));
        this.set(timer, run.throttle(this, this._onScroll, 100));
    }
});

Sticky Headers

Any plans to implement sticky headers, so when you scroll you still see the column/group headings?

Fixed left column

One of the requirements I was given was to implement the first column as a fixed column. Much like http://opensource.addepar.com/ember-table/#/overview. If you collapse the width of the page, you will see that you can scroll everything but the first column to the right. This gives a much better presentation on mobile/tablet. Can you guys think of a way that I might accomplish this?

Resizable columns?

Hey guys i love light table, it has everything out of the box with a simple config, but is it possible to have resizable columns in any way?

yielding row

This is similar to #2.
I have a few tables in an ember application that use a component for a row. Can light-table or one of the contextual components yield an individual or something like that? My use case is to customize the HTML of each row.

{{#t.body as |body row|}}
{{my-row-component row=row}}
{{/t.body}} 

I would need to this to happen before the user clicks on a row, so body.expanded-row wouldn't apply. There doesn't seem to be a way to customize the HTML of the individual rows. I'm open to other ideas too.

Implicit creation of rows when new data added to model?

I've noticed that you have to manually call table.addRow() if you'd like a new row to appear in the table. Is it possible to have the table watch the initial passed in model to the constructor for changes? Or is adding rows at runtime not really a priority feature for this table addon?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.