Display footer in PrimeFaces template, when fullPa

2020-02-11 08:43发布

Footer is not displayed (actually, it is incorrectly displayed on top of the page), when fullPage is set to false in PrimeFaces template.

<p:layout fullPage="false">
    <p:layoutUnit position="north" size="135">
        <!--Put north content here, if any-->
    </p:layoutUnit>

    <p:layoutUnit position="west" size="225" header="Menu Item" collapsible="true">
        <!--Put west content here, if any-->
    </p:layoutUnit>

    <p:layoutUnit position="center" size="2500" maxSize="2500">
        <!--Put center content here, if any-->
    </p:layoutUnit>

    <p:layoutUnit position="east" size="175">
        <!--Put east content here, if any-->
    </p:layoutUnit>

    <p:layoutUnit position="south" size="90">
        <!--Put south/footer content here, if any-->
    </p:layoutUnit>
</p:layout>

How to display footer, when fullpage is set to false?


EDIT :

if <p:layout> is given a height like as follows,

<p:layout fullPage="false" style="height: 2000px;">

then the footer is displayed at the bottom of the page based on the value of the height CSS attribute but it is still not a sticky footer - it does not adjust according to the page contents.

So, Is there a way to make it sticky?


Update :

The behaviour remains stationary on PrimeFaces 5.3 final (community release), when fullPage is set to false as said previously throughout the question.

4条回答
一纸荒年 Trace。
2楼-- · 2020-02-11 08:49

To easily visualize what you ultimately need (and to confirm your needs for myself), here's in SSCCE flavor a pure HTML/CSS solution of what you're (apparently) asking for. The sticky footer solution is largely based on Ryan Fait's approach (a min-height:100% and a negative margin on the container element which covers everything but footer), it only doesn't support IE6/7 anymore (due to :after pseudoselector), hereby simplifying the HTML markup (no non-semantic clutter like <div id="pushfooter"> needed). Note: background colors are purely for visualization.

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Stack Overflow Question 22584920</title>
        <style>
            html, body {
                height: 100%;
                min-width: 800px;
                margin: 0;
            }
            #container {
                min-height: 100%;
                margin: 0 auto -90px; /* Negative of #footer.height */
            }
            #header {
                height: 135px;
                background: pink;
            }
            #menu {
                float: left;
                width: 225px;
                background: khaki;
            }
            #content {
                margin-left: 225px; /* Same as #menu.width */
                margin-right: 175px; /* Same as #side.width */
                background: lemonchiffon;
                padding: 1px 1em; /* Fixes collapsing margin of p's on div, feel free to remove it */
            }
            #side {
                float: right;
                width: 175px;
                background: palegreen;
            }
            #footer, #container:after {
                height: 90px;
            }
            #footer {
                background: orange;
            }
            .clearfix:after {
                display: block;
                content: " ";
                clear: both;
            }
        </style>
    </head>
    <body>
        <div id="container" class="clearfix">
            <div id="header">Header</div>
            <div id="menu">Menu</div>
            <div id="side">Side</div>
            <div id="content">
                <p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p>
            </div>
        </div>
        <div id="footer">Footer</div>
    </body>
</html>

Note: due to the way how floats work, the <div id="side"> (the "east unit") has in the HTML markup to be placed before all non-floating elements at the same "row", such as the <div id="content"> (the "center unit"), otherwise it will be aligned relative to the bottom of the last non-floating element.

Now, in order to achieve exactly the same with the <p:layout> thing, which basically renders almost the same HTML structure, only with the footer still inside the container and the east unit after the center unit, you need to make sure that no one of the layout units are collapsible/closable/resizable (those attributes all already default to false and can thus be omitted for brevity) and that you apply the PrimeFaces-builtin clearfix style class ui-helper-clearfix on the container unit to clear the floats (otherwise the menu, content and side would overlap the footer when the screen is shrunk vertically):

<p:layout styleClass="ui-helper-clearfix">
    <p:layoutUnit position="north" size="135">
        <p>Header</p>
    </p:layoutUnit>
    <p:layoutUnit position="west" size="225" header="Menu Item">
        <p>Menu</p>
    </p:layoutUnit>
    <p:layoutUnit position="center">
        <p>Content</p>
        <p>Content</p>
        <p>Content</p>
        <p>Content</p>
        <p>Content</p>
    </p:layoutUnit>
    <p:layoutUnit position="east" size="175">
        <p>Side</p>
    </p:layoutUnit>
    <p:layoutUnit position="south" size="90">
        <p>Footer</p>
    </p:layoutUnit>
</p:layout>

Then you can apply the following CSS in your PrimeFaces-override stylesheet to remove/override all "irrelevant" PrimeFaces-generated CSS properties on those layout units by setting the absolute positioning with fixed offsets/dimensions back to initial/default values (note: the exact purpose of !important is being able to override hardcoded/inline style properties from a true stylesheet on, there's in this particular case simply no other option as long as you don't want to rewrite PrimeFaces components and renderers). Key point is that you should end up with exactly the same HTML/CSS (defaults) as the SSCCE:

html, body {
    height: 100%;
    min-width: 800px;
    margin: 0;
}
.ui-layout-container {
    min-height: 100%;
    height: auto !important;
    margin: 5px;
    margin-bottom: -90px; /* Negative of footer height. */
}
.ui-layout-unit {
    position: static !important;
    top: auto !important;
    bottom: auto !important;
    left: auto !important;
    right: auto !important;
    height: auto !important;
}
.ui-layout-unit-content {
    display: block !important;
    height: auto !important;
}
.ui-layout-west {
    float: left;
    margin: 5px 0 !important;
}
.ui-layout-center {
    margin: 5px 0 !important;
    margin-left: 230px !important; /* Menu width plus margin between panels. */
    margin-right: 180px !important; /* Side width plus margin between panels. */
}
.ui-layout-east {
    float: right;
    margin: 5px 0 !important;
}
.ui-layout-container:after {
    height: 85px; /* Footer height minus margin between panels. */
}
.ui-layout-south {
    margin: 5px !important;
    visibility: visible !important;
}

And finally add the following script in order to move the side (east unit) before the content (center unit), so that the floats go as intented, and to move the footer to end of body, so that it's outside the container element:

$(function() { 
    $(".ui-layout-east").insertBefore(".ui-layout-center");
    $(".ui-layout-south").appendTo("body");
});

Make sure that this script is re-executed when you do an ajax update with @all on the same view for some reason (which is at its own a bad idea though).

With this "solution" (I'd rather call it a hack and just throw it all away and go for a sane and clean HTML/CSS solution, if necessary with <p:panel>s instead of <div>s), it's still somewhat brittle; the auto-included layout.js script auto-adjusts the layout units on every window resize. But so far they don't seem to break anything in all modern browsers I tried (IE>8).

查看更多
地球回转人心会变
3楼-- · 2020-02-11 08:56

This may or may not be a bug in PrimeFaces - you're best off asking there. The layout is actually on your page if you check the source, however its positioning is above the header, likely because it has no idea where it's to be. In a full page it knows its location generated by the page, but otherwise it could be anywhere you want it to be. Try using CSS to move it etc, refer to. and use styleClass etc to attach classes, my hack was just to use !important which you shouldn't really do.

.ui-layout-pane-south {
    top: 200px !important;
}

etc..

Although I am more inclined to think this is a bug as none of the CSS is applied properly to it.

I've created an issue report on PF and hopefully someone can give some more information on the problem.

查看更多
▲ chillily
4楼-- · 2020-02-11 09:03

Apparently <p:layout> requires an appropriate height, when fullPage is set to false. The height is required to display the footer at appropriate position (it should position at the bottom of the browser window) like,

<p:layout fullPage="false" style="height: 2000px;">

Learnt from PrimeFaces Extensions <pe:layout> which fails to work with the following error in JavaScript alert box on page load,

/ UI Layout Initialization Warning The layout-container "DIV#mainForm:fullPage" has no height. Therefore the layout is 0-height and hence 'invisible'!

if fullPage of <pe:layout> is set to false and height is not defined. For it to work appropriately, it needs an appropriate height like as follows.

<pe:layout id="fullPage" 
           fullPage="false" 
           style="height: 2000px;" 
           stateCookie="true">

It is difficult to tell whether it is deliberate or intentional.


It would be delightful, if someone could expose how to adjust the footer according to the page contents, a sticky footer.

查看更多
戒情不戒烟
5楼-- · 2020-02-11 09:12

To ensure that the layout DIV has a relative height :

1_ Every components between the BODY and the layout must have a relative height, witch should be 100%.

2_ Always use DIV instead of SPAN between the BODY and your layout (no inline elements).

exemple :

<body>
<h:panelGroup layout="block***important***" style="height:100%" >
    <pe:layout widgetVar="pageLayoutWV" fullPage="false" style="height:100%" > 
    </pe:layout>
</h:panelGroup>
</body>

In case, it dosent work add this code to your page, (i fixed a long time ago but its probably has a relationship with your problem) :

function BaseWidgetInit(cpn, cfg) {
    cpn.cfg = cfg;
    cpn.id = cfg.id;
    cpn.jqId = PrimeFaces.escapeClientId(cpn.id),
    cpn.jq = $(cpn.jqId);           
    //remove script tag
    $(cpn.jqId + '_s').remove();
}   
if (PrimeFaces.widget.Layout)
PrimeFaces.widget.Layout = PrimeFaces.widget.Layout.extend({
    init: function(cfg) {
        BaseWidgetInit(this, cfg);        
        this.cfg = cfg;
        this.id = this.cfg.id;
        this.jqId = PrimeFaces.escapeClientId(this.id);
        if(this.cfg.full) {                                                 //full
            this.jq = $('body');
        } else if(this.cfg.parent) {                                        //nested
            this.jq = $(PrimeFaces.escapeClientId(this.cfg.parent));
        } else {                                                            //element
            this.jq = $(this.jqId);
            this.jq.css('height', $(window).height()-10);
        }        
        var _self = this;
        $(this.jq).data("layoutContainer", null);
        $(this.jq).data("layout", null);
        if(this.jq.is(':visible')) {
            this.render();
        } 
        else {
            var hiddenParent = this.jq.parents('.ui-hidden-container:first'),
            hiddenParentWidget = hiddenParent.data('widget');

            if(hiddenParentWidget && hiddenParentWidget.addOnshowHandler) {
                hiddenParentWidget.addOnshowHandler(function() {  
                    return _self.render();
                });
            }
        }
    }
});

i also suggest you, to use the layout of PF Extention library, its more stable, a working template can be found here erp.agitech.net admin/pass

查看更多
登录 后发表回答