Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

column header misalignment with body in version 11.1.2 ( same code works in 11.0.4 ) #1145

Open
darkurse opened this issue Nov 22, 2017 · 24 comments

Comments

@darkurse
Copy link

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, post on Stackoverflow or Gitter

Current behavior
With the same typescript code on my side, I have a different rendering depending on ngx-datatable version I use :

This is what I have with ngx-datatable version 11.0.4
list-11 0 4

and with version 11.1.2
list-11 1 2

Expected behavior
Same rendering regardless of version

Reproduction of the problem

my-list component :

html

<ngx-datatable
    class="material fullscreen"                        
    [columnMode]="'force'"
    [rowClass]="getRowClass"
    [headerHeight]="50"
    [footerHeight]="50"
    [rowHeight]="50"
    [externalPaging]="true"
    [externalSorting]="true"
    [loadingIndicator]="loading"
    [limit]="pageSize"
    [offset]="pageOffset"
    [count]="totalCount"
    [rows]="items"
    [columns]="columns"
>

    <!-- Header template -->
    <ng-template #headerTemplate let-column="column">
        <span class="datatable-header-cell-wrapper"><span class="datatable-header-cell-label draggable text-truncate" (click)="sort()">{{ column.name | translate }}</span></span>
    </ng-template>

    <!-- Cell template -->
    <ng-template #cellTemplate let-column="column" let-value="value">
        <div [innerHTML]="getCellHtml(value, column) | safe: 'html'"></div>
    </ng-template>

    <!-- Actions template -->
    <ng-template #actionTemplate let-row="row" let-value="value">
        <!-- Buttons omitted -->
    </ng-template>
    
</ngx-datatable>

typescript

@Component({
  selector: 'my-list',
  [...]
})
export class MyListComponent implements OnInit, OnDestroy {
    @Input('searchFn') searchFn: (term: string) => Observable<any>;
    @Input('columnFn') columnFn: () => Observable<Columns[]>;
    @Input('getCellFn') getCellFn: (column: string, value: string) => string;
    [...]
    constructor(private el: ElementRef, private sanitizer: DomSanitizer) {}

    public ngOnInit() {
        // on init, get columns and then do search
        this._column().then(() => this._search(''));
    }

    private getCellHtml(value, column) : string
    {
        const type = typeof value;

        // Allow for column custom text
        if (this.getCellFn !== undefined) {
            var innerHtml = this.getCellFn(column.prop, value);
            if (innerHtml !== undefined)
                return innerHtml;
        }

        switch (type) {
            case 'string': {
                if (moment(value, moment.ISO_8601).isValid()) {
                    return moment(value).local().format('L');
                } else {
                    const sanitizedValue = this.sanitizer.sanitize(SecurityContext.HTML, value);
                    return `<span class="text-truncate">${sanitizedValue}</span>`;
                }
            }
            case 'boolean': {
                return value ? '<i class="material-icons">check</i>' : '';
            }
        }

        // Any other case, return value as is
        return value;
    }

    private _search(term: string) {
        this.searchFn(term).subscribe(result => this.items = [...result.items]);
    }

    private _column() {
        const promise = new Promise((resolve, reject) => { 

            this.columns = []

            this.columnFn()
                .flatMap(preferences => preferences) // yield array items
                .map(preference => {
                    return {
                        headerTemplate: this.headerTemplate,
                        cellTemplate: this.cellTemplate,
                        name: preference.description,
                        prop: preference.fieldName,
                        sortable: true,
                        draggable: true,
                        minWidth: undefined,
                        maxWidth: undefined,
                        _index: preference.fieldOrder
                    };
                })
                .toArray()
                .subscribe(
                    result => {
                        result.sort((a, b) => a._index - b._index)
                        result.push({
                            headerTemplate: this.headerTemplate,
                            cellTemplate: this.actionTemplate,
                            name: '',
                            prop: 'id',
                            sortable: false,
                            draggable: false,
                            minWidth: 100,
                            maxWidth: 100,
                            _index: result.length
                        });
                        this.columns = [...result];

                        // Resolve promise
                        resolve();
                    }
                );

        });
        return promise;
    }

}

Consuming my-list component :

html

<my-list #myList
    sortProp="'name'"
    [columnFn]="getColumnCallback"
    [getCellFn]="formatCellCallback">
</my-list>

typescript

    [...]

    /**
     * Return Observable of items from api service
     * Note: Notation 'public xxx = () => {}' is required in order to work correctly
     */
    public searchCallback = (term: string): Observable<any> => {
        return this.myHttpApiService.search(term);
    }


    /**
     * Return columns preferences Observable from api service
     * Note: Notation 'public xxx = () => {}' is required in order to work correctly
     */
    public getColumnCallback = () => {
        return this.myHttpApiService.getFormPreferences();
    }


    /**
     * Basic formatting is handled by MyListComponent. This handler is exclusively if you want to intercept columns
     * of 'string' type and format it as you need.
     * 
     * Note: Notation 'public xxx = () => {}' is required in order to work correctly ( This keeps 'this' valid )
     */
    public formatCellCallback = (column: string, value: string): string => {
        switch (column) {
            case 'gender': return this.getGenderIcon(value);
            case 'type': return this.getTypeLabel(value);
            default: return undefined;
        }
    }
    [...]

Please tell us about your environment:

windows 10 pro, vs code, npm, node

  • Table version: 0.8.x

11.0.4 vs 11.1.2

  • Angular version: 2.0.x

5.0.2

  • Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]

Chrome

  • Language: [all | TypeScript X.X | ES6/7 | ES5]
    typescript 2.6.1
@realshadow
Copy link

realshadow commented Nov 22, 2017

This might not be related but I am facing the same issue on version 9.3.1. It happens only when the table is inside md-tab. It will auto correct itself when I try to resize any column or when I wrap it in *ngIf

@darkurse
Copy link
Author

As a matter of fact I am within a mat-tab too.. This works fine on version 11.0.4, but not on 11.1.2.
ps: I saw that there is a version 11.1.3 but change logs shows nothing in regards to this particular issue.

@realshadow
Copy link

@darkurse any luck with a solution?

@darkurse
Copy link
Author

No, I was actually waiting for a suggestion from @amcdnl . I kind of suspect the force rendering mode.
I actually went back to 11.0.4.

Now I actually face a new issue with the force rendering : I need to print the datatable and because the column width are forced, my print view is larger than my paper. Therefore I am gonna try the flex mode again and let you know how it goes.

@realshadow
Copy link

@darkurse I am curious if you got it working. Flex doesnt work in my case. Only thing that works for me is creating "custom" tabs with ngIf.

@darkurse
Copy link
Author

darkurse commented Dec 1, 2017

@realshadow , no dice. Not working well. Seems like force is the only viable way up to 11.0.4. Thereafter things don't work well I'm afraid.

@hiper2d
Copy link

hiper2d commented Dec 5, 2017

I see this issue every time when the width and the maxWidth column's attributes have different values. Making them equal fix it.

@enniob
Copy link

enniob commented Dec 6, 2017

I have the same issue when I add a new column to the existing table. After I scroll left or down the columns align to the correct location.

@enniob
Copy link

enniob commented Dec 6, 2017

I was just able to fix this by setting the width, minWidth and maxWidth to the same value.

@darkurse
Copy link
Author

darkurse commented Dec 6, 2017

That's interesting. I'm curious to know what the contributors say about it. Do you think this would also fix the frozenLeft, frozenRight issues ?

@enniob
Copy link

enniob commented Dec 6, 2017

@darkurse I try adding the frozenLeft or frozenRight to my code and that does not fixes it. I still see all the other columns on top of the frozenLeft or frozenRight columns.

@darkurse
Copy link
Author

@hiper2d , @enniob . To give continuity to this thread, I think I found the source of the issue and offer a solution in issue #1165. I also made a PR which hopefully is the fix or at least can give a hint towards the right solution..

@darkurse
Copy link
Author

@amcdnl, could you make a new release ? It's been a long time and lots of PR have been made since then.
Thanks in advance

@darkurse
Copy link
Author

@amcdnl, could you please make a new release ?

Showing the datatable to customers with these horrible collapsed column headers is terrible !!

I've sent you a private message 2 weeks ago regarding this and the above message. I don't want to be a pain in the neck, but a simple yay or nay answer would be welcome !

Thank you

@darkurse darkurse reopened this Feb 20, 2018
@marjan-georgiev
Copy link
Member

marjan-georgiev commented Feb 20, 2018

Released 11.2.0

@pedrocleto
Copy link

Still not working in 11.2.0

@stewx
Copy link
Contributor

stewx commented Mar 1, 2018

Is this the same issue, or different? If it's different, I will log a new issue.

screencastgif

@enniob
Copy link

enniob commented Mar 1, 2018 via email

@stewx
Copy link
Contributor

stewx commented Mar 1, 2018

@enniob Can't see your images

@enniob
Copy link

enniob commented Mar 1, 2018

@stewx just uploaded the image, I had replies to the email and it didn't attached it.

@pedrocleto
Copy link

I get the same issue also when I change the display columns but if I have a scroll and scroll left it goes away. So looks like it is an issue with table refresh or columns recalculation.

@enniob
Copy link

enniob commented Mar 7, 2018

@pedrocleto is there a way to force a refresh? I'm calling this.datatable.recalculate(); but its not doing anything. A quick solution I used on my application was to clear all the data on the table and add it again.

@jcraddock
Copy link

In my case I was using the columns array to drive the datatable. I simply moved the initialization of the columns array to after the rows array was populated, and it started working correctly.

@mytzui
Copy link

mytzui commented Jun 20, 2019

For anyone still encountering this issue of misaligned headers to data rows at init:

In my scenario I was using angular flex layout library with property 'fxFlex="100"' assigned to the component.

This got fixed by simply moving the 'fxFlex' property on a wrapper

. Doesn't seem to play nicely with angular flex.

Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants