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

DataTable : Sticky Header - cannot filter or sort on 7.0.RC1 #4469

Closed
rmpestano opened this Issue Jan 23, 2019 · 21 comments

Comments

Projects
None yet
5 participants
@rmpestano
Copy link

rmpestano commented Jan 23, 2019

1) Environment

  • PrimeFaces version: 7.0.RC1

  • Does it work on the newest released PrimeFaces? no, works on v6.2

  • Application server + version: WildFly 13

  • Affected browsers: Chrome/Firefox

2) Expected behavior

Datatable should be sortable and filterable

3) Actual behavior

Can't sort or filter datatable

4) Steps to reproduce

Just create a datatable with stickyHeader=true and add a sortBy or filterBy column.

5) Sample XHTML

<h:body>
        <h:form>
            <p:dataTable var="car" value="#{datatableView.cars}" stickyHeader="true" rows="15">
                <p:column headerText="Id" sortBy="#{car.id}" filterBy="#{car.id}">
                    <h:outputText value="#{car.id}" />
                </p:column>
                <p:column headerText="Year">
                    <h:outputText value="#{car.year}" />
                </p:column>
                <p:column headerText="Brand">
                    <h:outputText value="#{car.brand}" />
                </p:column>
                <p:column headerText="Color">
                    <h:outputText value="#{car.color}" />
                </p:column>
            </p:dataTable>

            <div style="min-height: 1500px"></div>
        </h:form>
    </h:body>

6) Sample bean

@Named
@ViewScoped
public class DatatableView implements Serializable {

    private List<Car> cars;
    private Car selectedCar;

    private List<Car> filteredCars;

    @Inject
    private CarService carService;


    @PostConstruct
    public void init() {
        cars = carService.createCars(30);
    }

    public boolean filterByPrice(Object value, Object filter, Locale locale) {
        String filterText = (filter == null) ? null : filter.toString().trim();
        if (filterText == null || filterText.equals("")) {
            return true;
        }

        if (value == null) {
            return false;
        }

        return ((Comparable) value).compareTo(Integer.valueOf(filterText)) > 0;
    }

7) Sample maven project

Following is a sample project which reproduces described issue:

datatable.zip

Changing the version of PrimeFaces to 6.2 removes the issue.

@rmpestano rmpestano changed the title DataTable : Sticky Header cannot filter or sort on 7.0.RC1 DataTable : Sticky Header - cannot filter or sort on 7.0.RC1 Jan 23, 2019

@melloware

This comment has been minimized.

Copy link
Contributor

melloware commented Jan 23, 2019

Similar to:
#3847

@Rapster

This comment has been minimized.

Copy link
Member

Rapster commented Jan 23, 2019

I think @mertsincan might have an idea about this, see #1070

filter is disabled on purpose, see the line

this.clone.find('.ui-column-filter').prop('disabled', true);

@tandraschko tandraschko added duplicate and removed duplicate labels Jan 23, 2019

@Rapster

This comment has been minimized.

Copy link
Member

Rapster commented Jan 23, 2019

In my company, we customized our stickyHeader so the paginator gets sticky also and we don't face those issues. @Taichou I think we might need your brain on this one 😉

@rmpestano

This comment has been minimized.

Copy link
Author

rmpestano commented Jan 23, 2019

As @Rapster commented here it is enabled after the sticky headers are activated. IMO it is very strange, who uses sort or filter after scrolling the page?

@tandraschko

This comment has been minimized.

Copy link
Member

tandraschko commented Jan 23, 2019

I would remove all Inputs from the Sticky Header ;) but thats up to primetek

@melloware

This comment has been minimized.

Copy link
Contributor

melloware commented Jan 23, 2019

I personally think the Sticky Header needs some love. There are about 10-15 open items here around Sticky Header.

@mertsincan mertsincan self-assigned this Jan 24, 2019

@mertsincan mertsincan added the defect label Jan 24, 2019

@mertsincan

This comment has been minimized.

Copy link
Member

mertsincan commented Jan 24, 2019

This issue works fine with Elite version 6.2.x. I need to find the fixes in 7.0 version.

@mertsincan

This comment has been minimized.

Copy link
Member

mertsincan commented Jan 24, 2019

Please examine these codes;

on 7.0, setupStickyHeader function
setupStickyHeader: function() {
        var $this = this,
            table = this.thead.parent();

        this.clone = this.thead.clone(false);
        table.prepend(this.clone);

        this.stickyContainer = $('<div class="ui-datatable ui-datatable-sticky ui-widget"><table></table></div>');
        this.stickyContainer.children('table').append(this.thead);
        this.stickyContainer.css({
            position: 'absolute',
            width: 0,
            top: 0,
            left: 0,
            display: 'none',
            'z-index': ++PrimeFaces.zindex
        });
        this.jq.prepend(this.stickyContainer);

        this.stickyContainerHeight = this.stickyContainer.height();

        this.stickyScrollParent = this.jq.scrollParent();
        if (this.stickyScrollParent.is('body') || this.stickyScrollParent.is(document)) {
            this.stickyScrollParent = $(window);
        }

        if(this.cfg.resizableColumns) {
            this.relativeHeight = 0;
        }

        PrimeFaces.utils.registerScrollHandler(this, 'scroll.' + this.id + '_align', function() {
            var tableOffset = table.offset(),
                scrollTop = $this.stickyScrollParent.scrollTop();

            // check top and bottom bounds - the calculation is different if the scrollParent is the window or just a container
            var showStickyHeader = true;
            if ($.isWindow($this.stickyScrollParent[0])) {
                var tableTop = tableOffset.top,
                    tableBottom = tableTop + $this.tbody.height();
                if (scrollTop <= tableTop || scrollTop >= tableBottom - $this.stickyContainer.height()) {
                    showStickyHeader = false;
                }
            }
            else {
                var scrollParentOffset = $this.stickyScrollParent.offset(),
                    tableTop = tableOffset.top - scrollParentOffset.top,
                    tableBottom = tableTop + $this.tbody.height();
                if (tableTop >= 0 || tableBottom <= $this.stickyContainer.height()) {
                    showStickyHeader = false;
                }
            }

            if (showStickyHeader) {
                // refresh top
                $this.stickyContainer.css({ top: scrollTop - 1 });

                if ($this.cfg.resizableColumns) {
                    $this.relativeHeight = scrollTop - tableOffset.top; // TODO: this needs to be checked for the container case
                }

                // show if not already visible
                if (!$this.stickyContainer.is(':visible')) {
                    $this.stickyContainer.show();
                    $this.stickyContainer.addClass('ui-shadow ui-sticky');

                    // recalculate width + left after swichting from not-visible to visisble state
                    $this.stickyContainer.css({ width: table.outerWidth() });
                    if ($.isWindow($this.stickyScrollParent[0])) {
                        $this.stickyContainer.css({ left: tableOffset.left });
                    }
                    else {
                        var scrollParentOffset = $this.stickyScrollParent.offset();
                        $this.stickyContainer.css({ left: tableOffset.left - scrollParentOffset.left });
                    }
                }
            }
            else {
                // hide if not already hidden
                if ($this.stickyContainer.is(':visible')) {
                    $this.stickyContainer.hide();
                    $this.stickyContainer.removeClass('ui-shadow ui-sticky');
                }

                if ($this.cfg.resizableColumns) {
                    $this.relativeHeight = 0;
                }
            }
        });

        PrimeFaces.utils.registerResizeHandler(this, 'resize.sticky-' + this.id + '_align', null, function() {
            $this.stickyContainer.width(table.outerWidth());
        });

        //filter support
        this.clone.find('.ui-column-filter').prop('disabled', true);
    },
on 6.2.15, setupStickyHeader function
setupStickyHeader: function() {
        var table = this.thead.parent(),
        offset = table.offset(),
        win = $(window),
        $this = this,
        stickyNS = 'scroll.' + this.id,
        resizeNS = 'resize.sticky-' + this.id;

        this.stickyContainer = $('<div class="ui-datatable ui-datatable-sticky ui-widget"><table></table></div>');
        this.clone = this.thead.clone(false);
        this.stickyContainer.children('table').append(this.thead);
        table.prepend(this.clone);

        this.stickyContainer.css({
            position: 'absolute',
            width: table.outerWidth(),
            top: offset.top,
            left: offset.left,
            'z-index': ++PrimeFaces.zindex
        });

        this.jq.prepend(this.stickyContainer);

        if(this.cfg.resizableColumns) {
            this.relativeHeight = 0;
        }

        win.off(stickyNS).on(stickyNS, function() {
            var scrollTop = win.scrollTop(),
            tableOffset = table.offset();

            if(scrollTop > tableOffset.top) {
                $this.stickyContainer.css({
                                        'position': 'fixed',
                                        'top': '0px'
                                    })
                                    .addClass('ui-shadow ui-sticky');

                if($this.cfg.resizableColumns) {
                    $this.relativeHeight = scrollTop - tableOffset.top;
                }

                if(scrollTop >= (tableOffset.top + $this.tbody.height()))
                    $this.stickyContainer.hide();
                else
                    $this.stickyContainer.show();
            }
            else {
                $this.stickyContainer.css({
                                        'position': 'absolute',
                                        'top': tableOffset.top
                                    })
                                    .removeClass('ui-shadow ui-sticky');

                if($this.stickyContainer.is(':hidden')) {
                    $this.stickyContainer.show();
                }

                if($this.cfg.resizableColumns) {
                    $this.relativeHeight = 0;
                }
            }
        })
        .off(resizeNS).on(resizeNS, function() {
            $this.stickyContainer.width(table.outerWidth());
        });

        //filter support
        this.clone.find('.ui-column-filter').prop('disabled', true);
    },
@mertsincan

This comment has been minimized.

Copy link
Member

mertsincan commented Jan 24, 2019

@tandraschko, I think this issue is related to #834

@mertsincan

This comment has been minimized.

Copy link
Member

mertsincan commented Jan 24, 2019

Maybe, we can use position: sticky; in the future :) Details; https://css-tricks.com/position-sticky-2/

@tandraschko

This comment has been minimized.

Copy link
Member

tandraschko commented Jan 24, 2019

yep, that would be the best solution. Maybe for the next version?

@mertsincan

This comment has been minimized.

Copy link
Member

mertsincan commented Jan 24, 2019

My suggestion;
@tandraschko can revert your fix in #834. As you know, p:layout component is deplicated. We'll remove it in the future (Maybe, on 7.1). I suggest that users use our new grid systems instead of p:layout. Because, new generation designs are made with this kind of grid systems. Our all Premium layouts use our grid systems;
https://www.primefaces.org/ultima/
https://www.primefaces.org/roma/
https://www.primefaces.org/barcelona/
etc.

@mertsincan

This comment has been minimized.

Copy link
Member

mertsincan commented Jan 24, 2019

yep, that would be the best solution. Maybe for the next version?

  • It doesn't work on IE 😄 Maybe, we can find a workaround for it.
@tandraschko

This comment has been minimized.

Copy link
Member

tandraschko commented Jan 24, 2019

let me check that issue before reverting.

tandraschko added a commit that referenced this issue Jan 24, 2019

tandraschko added a commit that referenced this issue Jan 24, 2019

@tandraschko

This comment has been minimized.

Copy link
Member

tandraschko commented Jan 24, 2019

fixed.
i didn't revert as the handling in the old version was also not correct.
Works fine for me now.

@tandraschko

This comment has been minimized.

Copy link
Member

tandraschko commented Jan 24, 2019

Please test :D

@tandraschko tandraschko added this to the 7.0 milestone Jan 24, 2019

@rmpestano

This comment has been minimized.

Copy link
Author

rmpestano commented Jan 24, 2019

Hi, it works for me, thank you!

Note that the behavior is a bit different than in v6.2. Now the sort/filter headers comes enabled and are disabled when the sticky headers are activated. Makes a lot more sense to me.

@tandraschko

This comment has been minimized.

Copy link
Member

tandraschko commented Jan 24, 2019

reverted my changes for #834 as PrimeTek would like to stay with the old behavior that the sticky header has enabled filters.

So please retest after my next commit.

@tandraschko

This comment has been minimized.

Copy link
Member

tandraschko commented Jan 24, 2019

@rmpestano

This comment has been minimized.

Copy link
Author

rmpestano commented Jan 24, 2019

Yea, now it works like PF 6.2, thank you very much!

@mertsincan

This comment has been minimized.

Copy link
Member

mertsincan commented Jan 25, 2019

Thanks a lot, @tandraschko ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment