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

ContextMenu: cannot be conditionally toggled with ajax #9863

Closed
NicolaIsotta opened this issue Mar 3, 2023 · 6 comments · Fixed by #9866 or #9960
Closed

ContextMenu: cannot be conditionally toggled with ajax #9863

NicolaIsotta opened this issue Mar 3, 2023 · 6 comments · Fixed by #9866 or #9960
Assignees
Labels
🐞 defect Bug...Something isn't working workaround A workaround has been provided
Milestone

Comments

@NicolaIsotta
Copy link
Contributor

NicolaIsotta commented Mar 3, 2023

Describe the bug

If a context menu renderd value evaluates to false, it shouldn't be displayed even if it was displayed before.

Reproducer

<h:form>
    <p:commandButton value="Toggle context menu" action="#{testView.toggleContextMenu()}" update="@form" />

    <p:outputLabel id="text" value="Context menu enabled: #{testView.enableContextMenu}"/>

    <p:contextMenu id="contextMenu2" for="text" rendered="#{testView.enableContextMenu}">
        <p:menuitem value="Homepage" url="https://www.primefaces.org" icon="pi pi-home"/>
    </p:contextMenu>
</h:form>
@Data
@Named
@ViewScoped
public class TestView implements Serializable {

    private boolean enableContextMenu;

    @PostConstruct  
    public void init() {
        enableContextMenu = true;
    }

    public void toggleContextMenu() {
        enableContextMenu = !enableContextMenu;
    }

}

To reproduce: open the page, press the button and right click the text: the context menu appears even if it shouldn't.

Expected behavior

if rendered evaluates to false, context menu shouldn't be displayed

PrimeFaces edition

Community

PrimeFaces version

12.0.0

Theme

No response

JSF implementation

Mojarra

JSF version

2.3.19

Java version

jdk-11.0.13

Browser(s)

No response

@NicolaIsotta NicolaIsotta added ‼️ needs-triage Issue needs triaging 🐞 defect Bug...Something isn't working labels Mar 3, 2023
@NicolaIsotta
Copy link
Contributor Author

If update="@form" is replaced by ajax="false", the behavior is correct.
Replacing update="@form" with update="contextMenu2" instead does not fix the issue.

@jepsar
Copy link
Member

jepsar commented Mar 3, 2023

ajax="false" will re-initialize all Javascript objects as you do a full reload of the page. update="contextMenu2" is not valid, see https://stackoverflow.com/questions/14790014/ajax-update-render-does-not-work-on-a-component-which-has-rendered-attribute, but if you would update a wrapper, the result will probably be the same.

@melloware
Copy link
Member

I think I know the issue. Let me try something.

@melloware melloware removed the ‼️ needs-triage Issue needs triaging label Mar 3, 2023
@melloware
Copy link
Member

melloware commented Mar 3, 2023

Reproducer:
pf-9863.zip

OK so the issue is because when its created its registering contextMenu events on the target. When it gets updated and rendered="false" there is nothing removing that $(document).contextMenu event so it still subscribed in the DOM.

So I have added a destroy method but when the update is applied and its no longer rendered I thought the destroy widget method would be called to cleanup these listeners but its not being called.

@melloware
Copy link
Member

@NicolaIsotta working workaround for you!
pf-9863.zip

if (PrimeFaces.widget.ContextMenu) {

    PrimeFaces.widget.ContextMenu.prototype._cleanup = function() {
        if (this.cfg.target === undefined) {
            var event = 'contextmenu.' + this.id + '_contextmenu';
            $(document).off(event);
            if (PrimeFaces.env.isTouchable(this.cfg)) {
                $(document).swipe().destroy();
            }
        }
        else {
            var event = this.cfg.event + '.' + this.id + '_contextmenu';
            $(document).off(event, this.jqTargetId);
            if (PrimeFaces.env.isTouchable(this.cfg)) {
                this.jqTarget.swipe().destroy();
            }
        }
    }
}
<p:commandButton 
value="Toggle context menu" 
action="#{testView.toggleContextMenu()}" 
update="@form" 
onstart="PF('cm')._cleanup();" />

@NicolaIsotta NicolaIsotta changed the title ContextMenu: cannot be conditionally toggled ContextMenu: cannot be conditionally toggled with ajax Mar 3, 2023
@melloware melloware added the workaround A workaround has been provided label Mar 3, 2023
@melloware melloware self-assigned this Mar 3, 2023
@melloware melloware added this to the 13.0.0 milestone Mar 3, 2023
@melloware
Copy link
Member

Because this is a special case and it can't tell the widget is being updated in 13.0.0 you will just have to call onstart="PF('cm').destroy();" to destroy the widget before the AJAX request is sent and when it responds it will rebuild the widget based on the rendered flag.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐞 defect Bug...Something isn't working workaround A workaround has been provided
Projects
None yet
3 participants