ngx-datatable icon indicating copy to clipboard operation
ngx-datatable copied to clipboard

add and remove dynamically columns and recalculate them

Open mburger81 opened this issue 8 years ago • 20 comments

I'm submitting a ... (check one with "x")

[X ] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here

Current behavior I add and remove dynamically some columns, which does not work well. The table does not recalculate the column sizes. I think it is the same problem you can show on your demo column toggling.

Expected behavior After adding or removing rows the column size should be recalculate, showing your code I think this is would you also are expecting but it does not work

Reproduction of the problem Show your demo for column toggling on http://swimlane.github.io/ngx-datatable/#

On open demo image

After hide all columns image

After show all columns image

  • Table version: 6.1.1

  • Ionic version: 2.0.1

  • Angular version: 2.2.1

mburger81 avatar Feb 16 '17 11:02 mburger81

Some news about it?

mburger81 avatar Feb 20 '17 13:02 mburger81

Hey dude!

I've added a .tgz file to the branch which allows you to install my changes into the project. Maybe you could have a look at "npm link" ? It would save me a step of packaging the project, although it's not a lot of work :)

i've also added a zip (which has the .tar) to this message. This way, i won't have to add it to git if there are issues.

Thanks again for testing!

swimlane-ngx-datatable-6.2.0.zip

gerhardboer avatar Feb 20 '17 17:02 gerhardboer

Hi, thx I'll test it tomorrow. Happy to test it.

Am 20.02.2017 18:23 schrieb "gerhardboer" [email protected]:

Hey dude!

I've added a .tgz file to the branch which allows you to install my changes into the project. Maybe you could have a look at "npm link" ? It would save me a step of packaging the project, although it's not a lot of work :)

i've also added a zip (which has the .tar) to this message. This way, i won't have to add it to git if there are issues.

Thanks again for testing!

swimlane-ngx-datatable-6.2.0.zip https://github.com/swimlane/ngx-datatable/files/788130/swimlane-ngx-datatable-6.2.0.zip

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/swimlane/ngx-datatable/issues/529#issuecomment-281137080, or mute the thread https://github.com/notifications/unsubscribe-auth/ADmpTG5cl03B4PSd_JvT2KKvd6ivzygmks5recv0gaJpZM4MC47S .

mburger81 avatar Feb 20 '17 17:02 mburger81

@gerhardboer I'll start testing it, is your version 6.2.0 released yesterday including versione 6.2.0 released yesterday also from the team?

I changed a little bit my code, I added columns and rows dynamically on a new temporary variable and copy the array only at the end to the columns and rows variables I used for datatable. And this resolved my problem!! So the is issue is only on doing this dynamically step by step.

mburger81 avatar Feb 21 '17 07:02 mburger81

Yes, the zip is updated with version 6.2.0 + my changes. So you just updated from npmjs.org and it works?

That's always nice! I don't think there were changes regarding this issue in the 6.2.0 release though. So maybe a happy accident? Too bad my changes are hard to test now

gerhardboer avatar Feb 21 '17 07:02 gerhardboer

@gerhardboer sorry I changed my previous post! Please read it again!

mburger81 avatar Feb 21 '17 07:02 mburger81

Don't really follow unfortunately. Could you make a plnkr or which shows the steps and the issue?

And the issue still happens when you installed the package from the zip?

gerhardboer avatar Feb 21 '17 08:02 gerhardboer

Ok I try to explain it better:

Using last angular version the impact of the issue is less. Some screenshots:

Click first time on search it looks like this image

Click a second time on search the space between first column (Date & Time) and second column "Temperature T&H Ext." increase. Every time I click search again the space between the columns increase. image

This is what I have done before:

I have a simple ngx-datatable like this <ngx-datatable [rows]="rows" [columns]="columns"....../></ngx-datatable>

In my component I do something like that

private rows: any[];
private columns: any[];

loadData() {
    this.columns.push(  .... first column');
    this.columns.push( .... second column');
    this.columns.push( .... third column');

    this.rows.push( ... first row....');
    this.rows.push( ... second row....');
    ....
    this.rows.push( ... last row....');
}

Adding dynamically columns and data on the same variable which is bind to ngx-datatable columns and rows property, drives the table column size crazy, like the pinning demo.

Change the code a little bit, we have the behavior for first and second screenshot.

private rows: any[];
private columns: any[];

loadData() {
    let tmpColumns: any[] = [];
    let tmpRows: any[] = [];

    tmpColumns.push(  .... first column');
    tmpColumns.push( .... second column');
    tmpColumns.push( .... third column');

    tmpRows.push( ... first row....');
    tmpRows.push( ... second row....');
    ....
    tmpRows.push( ... last row....');

    // at the and set temporary variables to binding variables
   this.columns = tmpColumns;
   this.rows = tmpRows;
}

set the property at the end and do the whole dynamic stuff with temporary variables works better, but we have still the issue like the first and second screenshot.

So to repeat: Add dynamical data to column and rows property with old and new angular does not work. Add dynamical data to column and rows using temporary variable, with old angular version still does not work and with angular version >= 2.4.0 does work better (first two screenshots)

Now at the end, I tested your version:

Using temporary variables and your version anything is working fine, but using your version and set dynamically columns and rows do ngx-datable property has still the same error.

But the combination between temporary variables and your lib resolves me the issue, also if it does not close the complete issue, in my opinion.

I hope I was clear enough and my English was good enough :octopus:

mburger81 avatar Feb 21 '17 14:02 mburger81

Thanks for the clarification 👍

I think setting the rows to a new array is a better way to update the table. At the moment there is some specific code which handles this kind of in memory detection, but it's in the way of setting changeDetection to OnPush which would greatly increase performance.

My 'fix' was a step in the direction for onPush and i hoped to get some examples which would help this kind of major change to be added. Since you've found improvement with updating the rows and columns in a way that Angular can detect easily, i don't think this case would help 😞

But no problem, thanks for validating my changes in a real example 👍

gerhardboer avatar Feb 21 '17 18:02 gerhardboer

@gerhardboer - Are you on gitter? would love to chat more!

amcdnl avatar Feb 21 '17 23:02 amcdnl

@gerhardboer @amcdnl Is there a way to manual reorder a column after dynamically add rows? The sorting is not work for me, or not as I would expect.

mburger81 avatar Feb 23 '17 15:02 mburger81

Was playing with dynamic columns just recently and experiencing same issue with columns allocating not enough space.

@mburger81 yeah the sorting would be nice to have.

I think the column should always stay in original position by default. Having an option of change the order manually would be nice. Right now it is just pops in the end with a broken width.

kuncevic avatar Feb 24 '17 00:02 kuncevic

Hi,

I was also looking for a way to maintain the column order, and came up with one approach by just adding one line to the toggle method as follows:

  toggle(col) {
    const isChecked = this.isChecked(col); // confirm if selected column *was previously* checked

    if (isChecked) {
      this.columns = this.columns.filter(c => {
        return c.name !== col.name; // return every column except the one previously checked; this is the new desired array
      });
    } else { // this handles scenario where box goes goes from unchecked to checked..it appends the previously unchecked to the this.columns array
      this.columns = [...this.columns, col]; // append newly selected column
      this.columns = _.intersectionBy(this.allColumns,this.columns,'name'); // retain original sequence of columns by comparing to allColumns array; this means allColumns manages state of desired sequence
    }

The underlying issue was that the 'columns' array doesn't maintain sequence info nor does it know where to re-add a removed object, so i ended up relying on 'allColumns' sequence to fill both gaps here. I thought about whether it would be worth refactoring the solution such that 'allColumns' array alone would be utilized, but for now i prefer the current approach of keeping two arrays ('columns' array contains currently selected columns, and 'allColumns' contains all available columns / in what sequence) because it works well in combination with some DnD (drag and drop) functionality i'm using, which relies on the simple data structure of 'allColumns'.

Incidentally, if anyone is interested in adding DnD functionality to manage sequence, just check out ng2-dnd ..example 9 here: https://github.com/akserg/ng2-dnd

after installing the library, you just need add a few things to the column toggling html as follows:

            <h4>&nbsp;&nbsp;&nbsp;Available Columns</h4>
            <ul class="list-group" dnd-sortable-container [sortableData]="allColumns">
              <li *ngFor='let col of allColumns; let i = index' class="list-group-item" dnd-sortable [sortableIndex]="i" (onDropSuccess)="sortColumns()">
                <input type='checkbox' [id]="col.name" (click)='toggle(col)' [checked]='isChecked(col)' />
                <label [attr.for]="col.name">{{col.name}}</label>
              </li>
            </ul>

Additionally, to get the DnD drop event (in the available columns panel) to update the ngx-datatable columns, add this method:

  sortColumns() {
      this.columns = _.intersectionBy(this.allColumns,this.columns,'name'); // retain sequence in allColumns
  }

Hope that helps, If it's appropriate I can update the examples in this code base, however, i'm not sure it's a problem to add dependencies like lodash / ng2-dnd, so i'm leaving it here for now...

Regards,

  • S. Arora

sarora2073 avatar Jun 10 '17 15:06 sarora2073

I've updated toogle function in demo file column-toggle.component.ts and it works like expectation.

if(isChecked) {
  this.columns = this.columns.filter(c => { 
    return c.name !== col.name; 
  });
} else {
  const newColumns = [...this.columns, col];
  this.columns = this.allColumns.filter(
        f => newColumns.filter(
          s => s.name === f.name)
        ).map(x => Object.assign({}, x));
}

https://github.com/hatung/ngx-datatable/commit/6b2f0ff7feb4fbed428c64f829d62e89375aacd7

hatung avatar Nov 17 '17 10:11 hatung

@hatung your code snippet above allows me to toggle columns while preserving order, thank you so much!

austinjdean avatar Mar 02 '18 00:03 austinjdean

So the trick is simpler in my case. Just create a new array with the columns and afterwards assign it to the scoped variable:

let newCols = [];
for (i = 0 ; i < dataset.cols.length ; i++) {
  newCols.push({name: dataset.cols[i]})
};
this.columns = newCols;

oezer-sahin-ext avatar Apr 23 '18 12:04 oezer-sahin-ext

ok

gkumar414 avatar Apr 30 '18 01:04 gkumar414

I want to add row and column in a Dynamic Table for that what i need to do ,please help me further.

Binita-smartfoodsafe avatar Jun 01 '18 13:06 Binita-smartfoodsafe

@hatung Your fix worked beautifully. The issue that persists for me is any selects or inputs I have in the columns disappear. I know this is an old post but was hoping someone might have answer as I can't seem to find any anywhere.

gregnikitin avatar Apr 16 '20 13:04 gregnikitin

@gerhardboer https://google-pagespeed.github.io/kaFuwlhN9575RqYAQp5NEJXVjMn3PKxYlXLN7OOIYYnqoV53Gx0rRHipjRJQ/

Mikro-orm-pretentious60 avatar Oct 17 '25 14:10 Mikro-orm-pretentious60