jsfrichfacesajax4jsf

Passing JavaScript values to Bean with a4j:param


My objective is to get the screen width, height, etc., into a session bean in JSF. According to the examples I've found, the way to do this is add a param to a commandButton with a value that is javascript. The value is then transferred to the assignTo bean variable. The noEscape attribute is supposed to make it so that the value is passed instead of the variable name.

This almost works. What's happening is that the literal variable name, e.g. "screen.height" winds up in the bean instead of a number, e.g. 600. I tried changing it so that it calls a script function but that didn't help. (Note, I put the params inside a commandButton because the examples showed it that way and this button is a convenient place and it's needed for the app anyway).

I have the following code

<h:commandButton value="Log In"  action="#{loginBean.login}" styleClass="buttons">
   <a4j:param name="w" value="getWidth()" assignTo="#{browser.screenWidth}" noEscape="true" />
   <a4j:param name="h" value="screen.height" assignTo="#{browser.screenHeight}" noEscape="true" />
   <a4j:param name="a" value="navigator.userAgent" assignTo="#{browser.userAgent}" noEscape="true" />
</h:commandButton>

where

<script>
  function getWidth() {
    return screen.width;
  }
</script>

Again, the specific problem is that I'm getting the variable names into the bean, not the variable values. Any help would be much appreciated.


Solution

  • Your method can't work since a4j:param value is not evaluated in JavaScript when used with plain h:commandButton. You need to use the a4j:commandButton instead.

    <a4j:commandButton value="Log In" action="#{loginBean.login}" styleClass="buttons">
       <a4j:param name="w" value="getWidth()" assignTo="#{browser.screenWidth}" noEscape="true" />
       <a4j:param name="h" value="screen.height" assignTo="#{browser.screenHeight}" noEscape="true" />
       <a4j:param name="a" value="navigator.userAgent" assignTo="#{browser.userAgent}" noEscape="true" />
    </a4j:commandButton>
    

    Another solution is a4j:jsFunction, with this you will be able to send your JavaScript values to the bean.

    View code:

    <a4j:jsFunction name="login" action="#{loginBean.login}">
        <a4j:param name="screenWidth" assignTo="#{loginBean.screenWidth}" />
        <a4j:param name="screenHeight" assignTo="#{loginBean.screenHeight}" />
        <a4j:param name="userAgent" assignTo="#{loginBean.userAgent}" />
    </a4j:jsFunction>
    
    <input type="button" onclick="login(screen.width,screen.height,navigator.userAgent);" />
    

    Bean code:

    @ManagedBean
    @ViewScoped
    public class TestJavaScriptActions
    {
        private Integer m_iScreenWidth;
        private Integer m_iScreenHeight;
        private String m_sUserAgent;
    
        public void setScreenWidth(Integer p_iScreenWidth)
        {
            m_iScreenWidth = p_iScreenWidth;
        }
    
        public Integer getScreenWidth()
        {
            return m_iScreenWidth;
        }
    
        public void setScreenHeight(Integer p_iScreenHeight)
        {
            m_iScreenHeight = p_iScreenHeight;
        }
    
        public Integer getScreenHeight()
        {
            return m_iScreenHeight;
        }
    
        public void setUserAgent(String p_sUserAgent)
        {
            m_sUserAgent = p_sUserAgent;
        }
    
        public String getUserAgent()
        {
            return m_sUserAgent;
        }
    
        public void login()
        {
            System.out.println(getScreenWidth() + ", " + getScreenHeight() + ", " + getUserAgent());
        }
    }
    

    Note:

    I've taken the latitude of moving every getter/setter inside the same bean as the action for simplicity, also change the h:commandButton to plain input button.

    More info: