2

I'm using a <p:selectCheckboxMenu multiple="true">

<p:selectCheckboxMenu id="options"
                      widgetVar="optionsCheckboxMenu"
                      value="#{someBean.selectedStrings}"
                      valueChangeListener="#{someBean.onSelectedOptionsChange}"
                      multiple="true">
    <f:selectItems id="items"
                   value="#{someBean.selectableStrings}" />
    <p:ajax process="@this"
            update="@this"
            onstart="var panelShown = $('#options_panel').css('display') == 'block';"
            oncomplete="console.log('PANEL SHOWN: ' + panelShown);
                        if (panelShown) { PF('optionsCheckboxMenu').show(); }" />
</p:selectCheckboxMenu>

The component uses a valueChangeListener="#{someBean.onSelectedOptionsChange}" which adjusts the selected items so they are valid, so I must use <p:ajax process="@this" update="@this" ...> in some way.

However, using update="@this" also has the effect of the component closing its related check box overlay panel. This can be remedied by calling PF('optionsCheckboxMenu').show(); in the oncomplete callback (see How to update the label of p:selectCheckboxMenu without the component being closed after ajax call in primefaces?).

The component however also lets you remove items via the X's in the input (when no panel is being displayed). The PF('optionsCheckboxMenu').show(); will display the overlay at all times.

What I want now is, to detect, before the AJAX request is sent, which state the overlay panel has currently, so that I only re-show the overlay panel if it was previously shown as well.

What I tried was to create a JavaScript var called panelShown in the onstart callback to evaluate that later in the oncomplete. However, when executing the oncomplete, the var panelShown is undefined.

QUESTION:

How do you carry over state (a simple JS var) from the PrimeFaces onstart to the oncomplete callback without having to go via some bean/remote command?

It occurrs to me that this should easily be possible, but I might be missing sth. right now.

PS: my form uses prependId="false".

Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102
Kawu
  • 13,647
  • 34
  • 123
  • 195

1 Answers1

0

The p:ajax onstart="..." and oncomplete="..." values are rendered in two separate JavaScript functions. Variables defined within a function are only available to that function. So you need to store your property globally somehow. A way to do that is using window, like:

window.panelShown = ...

in your onstart and access it in oncomplete like:

if (window.panelShown) { ... }

See also:

If you want to to get rid of hardcoded variable names, you might be interested in knowing that you can access the current component in Expression Language using #{component.clientId}. You can use this in combination with the PrimeFaces EL functions p:escapeJavaScriptVarName and p:resolveWidgetVar and the JavaScript API function PrimeFaces.escapeClientId to get something generic like:

<p:ajax process="@this"
        update="@this"
        onstart="window.#{p:escapeJavaScriptVarName(component.clientId)}Shown=$(PrimeFaces.escapeClientId('#{component.clientId}')+'_panel').css('display')=='block';"
        oncomplete="if(window.#{p:escapeJavaScriptVarName(component.clientId)}Shown){PF('#{p:resolveWidgetVar('@this', component)}').show()}" />

See also:

Jasper de Vries
  • 19,370
  • 6
  • 64
  • 102