Button behaviour

UI Components for JSF
Post Reply
propje
Posts: 4
Joined: 26 Jul 2010, 19:08

03 Aug 2010, 22:17

All, I am rather new to this and I was wondering if the behaviour of a button can be as follows:

As long as a button is pressed, the boolean value of a managed bean should be true. In all other cases the boolean value should be false.

Does primefaces have a component for this? If not, is it difficult to program one myself?

Thanks!!

wobblycogs
Posts: 47
Joined: 19 Apr 2010, 19:09
Location: Gloucester, UK

03 Aug 2010, 22:37

Create a bean with the boolean value set to false. Use the action or actionListener attribute in p:commandButton to call a method that sets the boolean value to true.
PrimeFaces 3.0.1, Mojarra 2.1.3, GlassFish 3.1.1, Netbeans 7.0, Firefox 7

cagatay.civici
Prime
Posts: 18616
Joined: 05 Jan 2009, 00:21
Location: Cybertron
Contact:

03 Aug 2010, 23:16

Do you mean a button with checkbox behavior?

Here is an example;

http://jqueryui.com/demos/button/checkbox.html

propje
Posts: 4
Joined: 26 Jul 2010, 19:08

04 Aug 2010, 08:44

Optimus: I don't mean a button with checkbox behaviour.

Actually I want to make a start-button for a machine. This means that, only when the button is pressed down, the boolean should be true. When the button is not pressed, the value should be false.

Wobblycogs: As I said, I am rather new. I already read a lot of stuff, and have some understanding of the action and actionListener attribute, but I didn't get it to work properly. I just managed to get the value true when I pressed the button. When I released the button, nothing happened. Can you please help me a bit more?

What makes it, for me, more difficult is that I made a custom component for this button (I want to use it on more than one place).
I was able to
1/ create a managed bean for this custom component and
2/ get the boolean variable into my custom component via the cc:attribute tag
But I am not able to call the boolean variable of the custom component from my managed bean. So, when I use the action or actionListener attribute to call a method in my managed bean, I can't do anything with it because I can not get the boolean value from the custom component.

Any help?

Thanks!!

wobblycogs
Posts: 47
Joined: 19 Apr 2010, 19:09
Location: Gloucester, UK

04 Aug 2010, 12:36

Ok, I misunderstod what you were trying to do in your original post. Using just the action or actionListener isn't going to be enough. Fortunately PF has the ability to do what you want without resorting to writing your own compnent. I've never seen a button in a web application like the one you are asking for so I thought I'd have a go at creating it for you and here's the result.

Code: Select all

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
	  xmlns:f="http://java.sun.com/jsf/core"
	  xmlns:p="http://primefaces.prime.com.tr/ui">
	<f:view>
		<h:head>
			<title>Machine Control</title>
		</h:head>
		<h:body>
			<h:form prependId="false">
				<h1><h:outputText id="msg" value="The machine is #{deadMansSwitch.friendlyState}"/></h1>
				<br/>
				<p:commandButton value="Start the Machine!">
					<p:ajax event="mousedown" actionListener="#{deadMansSwitch.switchOn}" update="msg"/>
					<p:ajax event="mouseup" actionListener="#{deadMansSwitch.swtichOff}" update="msg"/>
				</p:commandButton>
			</h:form>
		</h:body>
	</f:view>
</html>

Code: Select all

package com.example;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;

@ApplicationScoped
@Named( "deadMansSwitch")
public class DeadMansSwitch {

	private boolean switchState = false;

	public DeadMansSwitch() {
	}

	public boolean isSwitchState() {
		return switchState;
	}

	public void setSwitchState(boolean switchState) {
		this.switchState = switchState;
	}

	public String getFriendlyState() {
		if( isSwitchState() ) {
			return "On. Stand well back!";
		} else {
			return "Off.";
		}
	}

	public void switchOn() {
		setSwitchState( true );
	}

	public void swtichOff() {
		setSwitchState( false );
	}

}
When the button is pressed the switchOn method gets called, when it's released the switchOff method is called. The p:ajax actions also update the message to show the user the current machine state, you could alternativly update the button itself I suppose.

IMHO though I would think long and hard about controlling machinery with a web application unless you have a lot of other fail safes in place. What you are asking for is akin to a dead mans switch but web applications make no guarantee about when an action will get processed or even if a request will ever get to the server to get processed. Imagine what would happen if the user pushed the button to start the machine and the browser crashed - potentially the server would never get the onmouseup event to switch the machine off! A better approach would be a button that needs to be pressed every 30 seconds or the machine turns itself off - that forces a positive action on the part of the user and the machine fails to a safe state.
PrimeFaces 3.0.1, Mojarra 2.1.3, GlassFish 3.1.1, Netbeans 7.0, Firefox 7

propje
Posts: 4
Joined: 26 Jul 2010, 19:08

04 Aug 2010, 21:33

wobblycogs, thanks for the great response!

You are correct when you are telling me to think over it again. The web-application will serve as a sort of scada system. But there is a PLC (including fale-safe equipment) that will be between the web-application and the machine. Safety of the machines will of course be a primary issue since, with the web application, a machine can be started from a distance.

Regarding the start-button, you are correct. I will never be sure that the switchOff will occur. But I need a pulse of a certain length (just a bit longer than the repeat-cycle of the PLC).

I have found a solution in order to overcome the problem that the server does not get the request. I just let the server put the value back on false after some time by using a Thread command in an asynchronous method. According to me, this method works well:

Code: Select all

@ManagedBean
@RequestScoped
public class boolMonostableButton {

    private boolean tempValue = false;    

    /** Creates a new instance of boolMonostableButton */
    public boolMonostableButton() {
    }

    public String btnDown() {
        tempValue = true;
        changeValue();
        return null;
    }

    @Asynchronous
    public void changeValue() {
        try {
            Thread.sleep(3000);
            tempValue = false;
        } catch (InterruptedException ex) {
            tempValue = false;
        }
        tempValue = false;
    }
}
Because I will use this button to do several things (startup machine, switch on lights from different places, ...), I still want to use it in a custom component. As shown in the code of boolMonostableButton I am using a local variable for testing purposes. My custom component looks like this:

Code: Select all

    <!-- INTERFACE -->
    <cc:interface>
        <cc:attribute name="value"
                      required="true"
                      type="java.lang.Boolean"
                      shortDescription="Boolean that is changed when pressed on the button"/>
    </cc:interface>

    <!-- IMPLEMENTATION -->
    <cc:implementation>
        <p:commandButton value="Knop" async="true">
            <p:ajax event="mousedown" actionListener="#{boolMonostableButton.btnDown}"/>
        </p:commandButton>
    </cc:implementation>
Now I have the following problem: How can I refer in the managed bean to the cc:attribute name="value" attribute?

Thanks for the help!!

If there are any comments or thoughts on my method, please let me know!

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: Google [Bot] and 11 guests