Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable page/form in JSF

Tags:

jsf

For my application I want to have users with different permissions. One permission would allow a user to view the data from my database, while another permission would allow them to edit the data. On log in I would check their permission to determine wether they can edit the data. I am looking for some way to disable the entirety of my page if the user has the read-only permission. Is there a simple way to disable everything within the <h:form> tag? I would need to be able to disable multiple pages, hopefully by just looking at one boolean in by backingbean. Any help would be greatly appreciated.

-EDIT-
Is there any containers or like that I could wrap around my inputs that could be set to disabled? This way I would only need to reference the diable in one place and could also leave each field to set its own disable property if that is needed in other logic I have?

like image 945
SomeFatMan Avatar asked Jun 30 '10 19:06

SomeFatMan


3 Answers

You can disable the buttons, links, input fields (everything that allows editing) etc... pointing them all to the same value in the backing bean.

<h:inputText disabled="#{!bean.permissionToWrite}">

I don't know any way to disable everything contained in a form, but you may not want to do that because you may want the user to submit search queries (i.e. a search box) withing the form.

Update: answering to the comment of Alex Larzelere.

IMHO in this case is better to use disabled rather than rendered because you may want to display the value of a field to the user in an inputText box, but not let him to modify it. If you don't render it, he can't see it. You could use outputText as well to display it but then you have to maintain two elements instead of one.

Update answering to the edit in the question: You can wrap your components inside a h:panelGroup for example and render it or not depending on your logic, but you can't disable the input fields that are inside from the h:panelGroup, you have to do it individually.

like image 159
pakore Avatar answered Nov 03 '22 03:11

pakore


This simple custom component can be used to wrap other components and it will disable them if used with the attribute disabled="true" or an EL expression evaluating to true. The way it's intended to work is that if a wrappped component is already disabled then it won't get enabled if disablePanel is used (or ajax re-rendered) with disabled="true". The component only attempts to disable UIInput & UICommand components, which I think is ok but could be changed.

xmlns:fnc="http://myco.co.uk/fnc"
...
<fnc:disablePanel disabled="#{bean.isItDisabled}">
   <h:inputText/>
   ...
</fnc:disablePanel>
...

UIDisablePanel.java

package uk.co.myco.component;

import java.io.IOException;
import javax.faces.component.*;
import javax.faces.context.FacesContext;

/*
 * @author Brendan Healey (Oversteer)
 */

@FacesComponent("uk.co.myco.component.UIDisablePanel")
public class UIDisablePanel extends UIComponentBase {

    private enum PropertyKeys {
        disabled;
    }

    public UIDisablePanel() {
        setRendererType(null);
    }

    @Override
    public void encodeBegin(FacesContext context) throws IOException {

        boolean toDisable = isDisabled();
        processDisablePanel(this, toDisable);
        //super.encodeBegin(context);
    }

    public void processDisablePanel(UIComponent root, boolean toDisable) {

        /*
         * The key point here is that a child component of <x:disablePanel> may
         * already be disabled, in which case we don't want to enable it if the
         * <x:disablePanel disabled= attribute is set to true.
         */

        for (UIComponent c : root.getChildren()) {
            if (c instanceof UIInput || c instanceof UICommand) {
                if(toDisable) { // <x:disablePanel disabled="true">
                    Boolean curState = (Boolean) c.getAttributes().get("disabled");
                    if(curState == null || curState == false) {
                        c.getAttributes().put("UIPanelDisableFlag", true);
                        c.getAttributes().put("disabled", true);
                    }
                }
                else { // <x:disablePanel disabled="false">
                    if(c.getAttributes().get("UIPanelDisableFlag") != null) {
                        c.getAttributes().remove("UIPanelDisableFlag");
                        c.getAttributes().put("disabled", false);
                    }
                }
            }

            if (c.getChildCount() > 0) {
                processDisablePanel(c, toDisable);
            }
        }

    }

    @Override
    public String getFamily() {
        // Got to override it but it doesn't get called.
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public boolean isDisabled() {
        return (boolean) getStateHelper().eval(PropertyKeys.disabled, false);
    }

    public void setDisabled(boolean disabled) {
        getStateHelper().put(PropertyKeys.disabled, disabled);
    }
}

disablepanel.taglib.xml

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib version="2.0"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd">
    <namespace>http://myco.co.uk/fnc</namespace>
    <tag>
        <tag-name>disablePanel</tag-name>
        <component>
            <component-type>uk.co.myco.component.UIDisablePanel</component-type>
        </component>
        <attribute>
            <name>disabled</name>
        </attribute>
    </tag>
</facelet-taglib>
like image 5
Oversteer Avatar answered Nov 03 '22 01:11

Oversteer


Omnifaces has a massAttribute taghandler for this with several options. The one that comes closed to what you need is

<o:massAttribute name="disabbled" value="true" target="javax.faces.component.UIInput">
    <h:outputLabel for="input1" />
    <h:inputText id="input1" />
    <h:outputLabel for="input2" />
    <h:inputText id="input2" />
    <h:outputLabel for="input3" />
    <h:inputText id="input3" />
</o:massAttribute>

This disables all components that extend from javax.faces.component.UIInput.

like image 2
Kukeltje Avatar answered Nov 03 '22 01:11

Kukeltje