7 Replies Latest reply on Jul 10, 2008 10:19 AM by mail.micke

    rich:columns howto add onclick for certain columns?

    mail.micke

      Hi

      I have a tricky use-case to which I'm trying to find a nice solution and need some help.

      My problem is that for some columns I want to call some java script functions for popping up new browser windows. The different functions will require one or more parameter, typically the value displayed in the cell. The values needed as parameters will come from the current row item being rendered.

      How can I do this?

      If it wasn't for the fact that I needed the cell value as a parameter I could have just defined a new String in the ColumnDescriptor class with the JS function to call, but it has to be dynamic with one or more parameter.

      The only thing I've thought of this far is to create a Facelets source tag and have loads of outputs where only one would be rendered by looking at the ColumnDescriptor.valueProperty but this doesn't feel nice.

      Any suggestion would be very welcome.

      Something like this is what I don't want to end up with:

      SoureTag.xhtml I wish to avoid :

      <a4j:outputPanel
       rendered="#{col.valueProperty eq 'getSomething1'}"
       style="margin: 0px 0px 0px 0px;padding: 0px 0px 0px 0px;width:100%;height:100%"
       onclick="javascript:myOnClick1('hello there', #{item[col.valueProperty]})">
       #{item[col.valueProperty]}
       </a4j:outputPanel>
      
      <a4j:outputPanel
       rendered="#{col.valueProperty eq 'getSomething2'}"
       style="margin: 0px 0px 0px 0px;padding: 0px 0px 0px 0px;width:100%;height:100%"
       onclick="javascript:myOnClick2'hello there')">
       #{item[col.valueProperty]}
       </a4j:outputPanel>
      
      <a4j:outputPanel
       rendered="#{col.valueProperty eq 'getSomething3'}"
       style="margin: 0px 0px 0px 0px;padding: 0px 0px 0px 0px;width:100%;height:100%">
       #{item[col.valueProperty]}
       </a4j:outputPanel>
      
      // and so on
      
      
      


      The code:

      XHTML, with dummy onclick:
      <rich:dataTable id="listingTable"
       value="#{sdb2.allPositionWrappers}"
       var="item"
       rows="25"
       style="width:95%;">
       <f:facet name="header">
       <rich:columnGroup>
       <rich:column colspan="#{sdb2.visibleColumnCount}">
       <rich:datascroller for="listingTable"
       ajaxSingle="false"
       renderIfSinglePage="false"/>
       </rich:column>
       </rich:columnGroup>
       </f:facet>
       <rich:columns
       value="#{sdb2.columns}"
       sortBy="#{item[col.valueProperty]}"
       var="col">
       <f:facet name="header">
       <a4j:outputPanel layout="inline">
       #{col.header}
       </a4j:outputPanel>
       </f:facet>
       <a4j:outputPanel
       style="margin: 0px 0px 0px 0px;padding: 0px 0px 0px 0px;width:100%;height:100%"
       onclick="javascript:myOnClick('hello there')">
       #{item[col.valueProperty]}
       </a4j:outputPanel>
       </rich:columns>
       </rich:dataTable>
      



      Backing bean.
      Simply returns a list of ObjectWrappers (which are initialized via @Create)
       public void setAllPositionWrappers(List<ObjectWrapper> aAllPositionWrappers) {
       allPositionWrappers = aAllPositionWrappers;
       }
      



      ObjectWrapper.java. This class just wraps another object and access its properties via the Map interface.
      public class ObjectWrapper implements Map<String,Object>{
      
       private Object realObject;
      
       public ObjectWrapper(Object realObject){
       this.realObject = realObject;
       }
      
       public Object get(Object methodName) {
       Object retVal = invokeGetter(realObject, (String)methodName);
       return retVal;
       }
      
       @SuppressWarnings("unchecked")
       public Object invokeGetter(Object obj, String methodName){
       String getMethodName = null;
      
       if(!methodName.startsWith("get")){
       getMethodName = methodName.substring(0,1).toUpperCase();
       getMethodName = "get"+getMethodName+methodName.substring(1);
       }
       else{
       getMethodName = methodName;
       }
      
       Class c = obj.getClass();
      
       try {
       Method m = c.getMethod(getMethodName, new Class[]{});
       return m.invoke(obj,(Object[]) null);
      
       } catch (SecurityException e) {
       e.printStackTrace();
       } catch (NoSuchMethodException e) {
       e.printStackTrace();
       } catch (IllegalArgumentException e) {
       e.printStackTrace();
       } catch (IllegalAccessException e) {
       e.printStackTrace();
       } catch (InvocationTargetException e) {
       e.printStackTrace();
       }
      
       return null;
       }
       //cut
      



      ColumnDescriptor.java , describes one column.
      public class ColumnDescriptor {
      
       private String header;//column header
       private String footer;// column footer
       private String valueProperty;// How to get the value via reflections, ex: "getStartDate"
       private boolean visible; // Is column visible
      
       public ColumnDescriptor(String header, String footer, String valueProperty) {
       super();
       this.header = header;
       this.footer = footer;
       this.valueProperty = valueProperty;
       this.visible = true;
       }
      
       public boolean isVisible() {
       return visible;
       }
      
       public void setVisible(boolean visible) {
       this.visible = visible;
       }
      
       public String getHeader() {
       return header;
       }
       public void setHeader(String header) {
       this.header = header;
       }
       public String getFooter() {
       return footer;
       }
       public void setFooter(String footer) {
       this.footer = footer;
       }
       public String getValueProperty() {
       return valueProperty;
       }
       public void setValueProperty(String valueProperty) {
       this.valueProperty = valueProperty;
       }
      
      
      
      }
      



      Cheers,
      Micke



        • 1. Re: rich:columns howto add onclick for certain columns?
          mail.micke

          Getting desperate, so I'll bump this.

          Any suggestion appreciated... any at all.

          • 2. Re: rich:columns howto add onclick for certain columns?

            I'm not sure that I undersand your request properlly...

            But to add onclick only for certain column you can do something as:

            <rich:columns value="..." var="col" onclick="#{var.onclick}" />

            onclick - String javascript code, that you should put in model. Keep empty string for columns whose should be without onclick.

            • 3. Re: rich:columns howto add onclick for certain columns?
              mail.micke

              Hi

              My problem is that I want to pass parameters to the different javascript functions, parameters which will vary depending on which column is being rendered.

              But your example was very helpful, perhaps I could do something like the following.

              
              <rich:columns value="..." var="col" onclick="#{myfn:createOnClick(var,col)}" />
              
              


              Or put the logic in a backing bean, not mega nice but doable :)

              Cheers,
              Micke

              • 4. Re: rich:columns howto add onclick for certain columns?

                Also you can define one common JS function on the client and pass there all availible information about onclick event (column number, cell DOM instance, row number and etc) and then make decision which the following JS function should be invoked.

                Something as:

                function commonF (event, elt, rowN, colN) {
                ...
                }

                <rich:columns index="index" onclick="commonF(event, this, #{rowVar},#{index})" ../>

                • 5. Re: rich:columns howto add onclick for certain columns?
                  mail.micke

                  I would prefer to have all the onlick logic on the client side, but I'm not sure if it is possible.

                  The table in question is showing trades (financial), for the js function in certain columns I just want to pass in just the value in the cell but for others I need to also passin other values which is in the dataTables iteration variable.

                  The columns are also dynamic, the user can choose which columns that should be displayed.

                  Do you think it is doable to keep the logic on client side?

                  Many thanks for the help so far,
                  Micke

                  • 6. Re: rich:columns howto add onclick for certain columns?

                    In this case I think you need create onclick on server side. Because you should post parameters to function against exact column chosen by user to render.

                    Anyway there is no big difference between server and client side. In both you need dynamically rerender datatable content and onclick attribute will be rerendered too. And it does not matter if this attribute contain common client-side function invocation or javascript code generated on server-side.

                    • 7. Re: rich:columns howto add onclick for certain columns?
                      mail.micke

                      Will do!

                      Many thanks for all the pointers,
                      Micke