简体   繁体   中英

PrimeFaces p:selectOneMenu width

I want p:selectOneMenu width to be auto regarding to the parent cell not regarding to the values it has.

<p:panelGrid>
    <p:row>
        <p:column><p:outputLabel value="Value01" for="idInput01"/></p:column>
        <p:column><p:inputText  value="#{bean.input01}" id="idInput01" /></p:column>
        <p:column><p:outputLabel value="Value02" for="idSelect" /></p:column>
        <p:column>
            <p:selectOneMenu value="#{bean.selectedObject}" id="idSelect" converter="objectConverter">
                <f:selectItems value="#{bean.objectsList}" var="varObject" itemLabel="#{varObject.label}" itemValue="#{varObject}" />
            </p:selectOneMenu>
        </p:column>
    </p:row>
</p:panelGrid>

What I've got:

在此处输入图像描述

What I'm expecting:

在此处输入图像描述

Note: I don't want to specify a fixed width.

我的解决方案:autoWidth =“false”

i overrode .ui-selectonemenu, .ui-selectonemenu-label to:

.ui-selectonemenu{
     width: 100% !important;
}
.ui-selectonemenu-label{
     width: 100% !important;
}  

The only way I found is to use jQuery to initialize width at load time.

You can create simply a CSS class like this (just to be used as a futur selector ) :

.full-width
{

}

And add it to your component :

<p:selectOneMenu value="#{bean.selectedObject}" id="idSelect" converter="objectConverter" styleClass="full-width">
    <f:selectItems value="#{bean.objectsList}" var="varObject"  itemLabel="{varObject.label}" itemValue="#{varObject}" />
</p:selectOneMenu>

Since you will need jQuery , you should add this inside your h:head if you are not already using PrimeFaces components that use it.

<h:outputScript library="primefaces" name="jquery/jquery.js" />

Here is the small script that initialize all p:selectOneMenu in the selector :

<script>
    $(document).ready(
        function()
        {
            $("div.ui-selectonemenu.full-width").each(
                function()
                {
                    $(this).css("width",$(this).parent().width());
                }
            );
        }
    );
</script>

you can add the value of width directly in the component to modify it, to avoid impacting other p: selectOneMenu existing in the page.

<p:selectOneMenu  style="width: 100% !important">
...
</p:selectOneMenu>

I now have a proper fix for this.

Primefaces 6.0 now has a new field called autoWidth that by default is set to true, and you can set to false.

IF you do as some of the above responses say and set it to false, all you are doing is playing roulette with you app css. By setting it to false, primefaces will leave it up to you to manage the width. You can either have the width set on the selectOneMeny expliclitly by style attribute, or some css class in your application.

But this is not what this issue is about, this issue is about the fact that the default behaivor of not specifying any width to a drop down makes leads our drop downs to normally be way too small for the labels in there.

So what we actually want is for the autoWidth to work proplerly.

FInally, I looked at the component and at the renderer, and it is obvious the auto-width mechanism does not work in the backend side. The backend side only builds some JSON like data that the primefaces javascript builder can use to properly tune on the browser the behavior of the widget.

If you loook at primefaces 6.0 source code, the bug is in META-INF\\resources\\primefaces\\forms

Search for the code that says the following:

PrimeFaces SelectOneMenu Widget

In this javascript function hunt for the code chunk that says:

_render: function() {
        if(this.cfg.autoWidth) {

In this section of code your bug is the following line:

this.jq.css('min-width', this.input.outerWidth());

Here, I applied the following patch that hopefully should work in geting the drop down box to be as fat as the largest label:

 _render: function() {
        if(this.cfg.autoWidth) {
            // BEGIN: PATCHING 
            // ORIGINAL CODE:
            // this.jq.css('min-width', this.input.outerWidth());            
            // BUGFIX:
            // (a) compute the original min-with primefaces 6.0 would put on the root div
            var primefacesBugWidth = this.input.outerWidth();
            // (b) compute the length of the hidden select element  with all the labels inside of it
            var widthOfHiddenDivWithSelectLabels = this.jq.find('div select').width();
            var widthOfTheDropDownTriangle = this.jq.find('.ui-selectonemenu-trigger.ui-state-default.ui-corner-right').width();
            var widthOfLabelPlusTraingle = widthOfHiddenDivWithSelectLabels + widthOfTheDropDownTriangle;
            // (c) we will use whichever length is longer
            // in bug-fixed primefaces version the outerWidth should be computed correctly
            // but this seems not to be the case 
            var maxWidthOfTwoPossibleOptions = primefacesBugWidth > widthOfLabelPlusTraingle ? primefacesBugWidth : widthOfLabelPlusTraingle;
            this.jq.css('min-width', maxWidthOfTwoPossibleOptions);
            // END: PATCHING
        }        
    }

The idea of the code above is: (a) look at the hidden div with all labels and get the width of that div (b) add to that length the width needed for the primefaces triangle facing down (c) compare the width we have computed to that that is suggested by primefaces and that seems to be way too small

NOTE: To install the patch you have to copy all of the Primaces code for the SelectOneWidget. Add it to a javascript file under your control. Make sure you only run the compilation of your javascript file after the primefaces javascript file has been loaded.

Normally primefaces is being rendered at the HEAD. So if you have you jasvacript as the last ement in the body you should be fine.

The patching is working fine for me. THis is code I do not like to maintain however.

You can ID the element and change the style width through CSS. Make it 100% of its container.

If your p:selectOneMenu is in a DIV with an assigned width, I find setting style="width:100%;" on the p:selectOneMenu seems to work in my case.

The problem might be min-width, which is set in the rendered HTML. If that is your case, use a CSS selector fixed-width like this:

<p:selectOneMenu styleClass="fixed-width" ...

then define CSS

.fixed-width { min-width: 100% !important; }

That sets the width of the selectOneMenu widget to the width of the parent element. To have it work, parent elements's width should not be 'auto'.

Those who still got problem with selectonemenu may try this

.ui-selectonemenu {
    min-width: 0 !important;
}

Perfectly worked for me.

You can use something like

style="min-width: 12rem"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM