8 Replies Latest reply on Dec 1, 2008 7:01 AM by Mario Balaban

    can I put something else then strings into the calendarDataM

    Mario Balaban Newbie

      I'm developing an agenda using the rich:calendar. In each day cell I'd like to put a selectable and modifiable list of events of the day (similar to google calendar or the one in the teamwork project). I'm trying to put a instance of the ListaDataModel (containing objects with name property) into the HashMap used by the dataModel attribute of the calendar. Here is the code:


      <rich:calendar id="calendarAttivita" datePattern="dd/MM/yyyy"
       enableManualInput="false" popup="false" mode="ajax"
       styleClass="fontMedium" cellWidth="50px"
       dataModel="#{myDataModel}">
      
      
      
       <!-- Customization with usage of facets and accessible elements -->
      
      
      
       <f:facet name="weekDay">
      
       <h:panelGroup style="width:60px; overflow:hidden;" layout="block">
      
       <h:outputText value="{weekDayLabelShort}" />
      
       </h:panelGroup>
      
       </f:facet>
      
       <f:facet name="weekNumber">
      
       <h:panelGroup>
      
       <h:outputText value="{weekNumber}" style="color:red" />
      
       </h:panelGroup>
      
       </f:facet>
      
       <f:facet name="footer">
      
       <h:panelGrid columns="3" width="100%"
       columnClasses="fake, width100 talign">
      
       <h:outputText value="{previousMonthControl}"
       style="font-weight:bold;" />
      
       <h:outputText value="{currentMonthControl}"
       style="font-weight:bold;" />
      
       <h:outputText value="{nextMonthControl}"
       style="font-weight:bold;" />
      
       </h:panelGrid>
      
       </f:facet>
      
       <h:panelGrid>
      
       <f:facet name="header">
       <h:outputText value="{day}" />
       </f:facet>
      
       </h:panelGrid>
      
      
       <rich:dataList var="record"
       value="{data.eachDayDataList}">
       <h:outputText value="#{record.name}"></h:outputText>
       </rich:dataList>
      
      
       </rich:calendar>




      And this is the CalendarDataModel used by the attibute dataModel="#{myDataModel}"> in the calendar tag:



      public class myDataModel implements CalendarDataModel {
       @Override
       public CalendarDataModelItem[] getData(Date[] arg0) {
       if (arg0 == null) {
       throw new IllegalArgumentException(
       "Null date array argument for getData.");
       }
       CalendarDataModelItem[] items = new CalendarDataModelItem[arg0.length];
       for (int i = 0; i < arg0.length; i++) {
       items
       = createDataModelItem(arg0
      );
       }
      
       return items;
       }
      
       private CalendarDataModelItem createDataModelItem(Date date) {
       CalendarDataModelItemImpl item = new CalendarDataModelItemImpl();
       HashMap<String, Object> data = new HashMap<String, Object>();
       FacesContext facesContext = FacesContext.getCurrentInstance();
       ExternalContext externalContext = facesContext.getExternalContext();
       DefinitionManager definitionManager = (DefinitionManager) externalContext
       .getSessionMap().get("definitionManager");
       ListDataModel listDataModel = definitionManager.getScheduledJobList(date); // Here I'm retrieving
      the list for each day
      
       item.setEnabled(true);
      
      
       data.put("eachDayDataList", listDataModel);
      
      
       item.setData(data);
      
       return item;
       }
      
       @Override
       public Object getToolTip(Date arg0) {
       // TODO Auto-generated method stub
       return null;
       }
      
       public LavoriSchedulatiDataModel() {
       // TODO Auto-generated constructor stub
       }
      
      }
      
      






      the last class involved :

      public class CalendarDataModelItemImpl implements CalendarDataModelItem {
       HashMap<String, Object> data;
       int day;
       boolean enabled;
       Object toolTip;
       private String style;
      
       public Object getData() {
       // TODO Auto-generated method stub
       // return "9:00 Riunione<br/>10:00 Incontro Magistrato<br/>";
       return data;
       }
      
       /**
       * Returns: day of the month on which data must be shown.
       */
       public int getDay() {
       // TODO Auto-generated method stub
       return day;
       }
      
       public String getStyleClass() {
       return style;
       }
      
       public Object getToolTip() {
      
       return toolTip;
       }
      
       public boolean hasToolTip() {
      
       return toolTip != null;
       }
      
       public boolean isEnabled() {
      
       return enabled;
       }
      
       /**
       *
       * @param data
       * HashMap containing mappings like listaLavori ListaDataModel
       * containing the jobs
       */
       public void setData(HashMap<String, Object> data) {
       this.data = data;
       }
      
       public void setDay(int day) {
       this.day = day;
       }
      
       public void setEnabled(boolean enabled) {
       this.enabled = enabled;
       }
      
       public void setToolTip(Object toolTip) {
       this.toolTip = toolTip;
       }
      
       public void setStyleClass(String style) {
       this.style = style;
      
       }
      
      }





      But when I use the datamodel in this manner I get :java.lang.NoSuchMethodException: Property 'volatility' has no getter method.

      So my question is:
      can I put something else then strings (collections for example) into the HashMap used by the CalendarDataModel and the use them for uicomponents inside each day cell of the calendar ?

        • 1. Re: can I put something else then strings into the calendarD
          Nick Belaevski Master

          Hello,

          Yes, that should be possible. Have you tried to use simple collections instead of DataModel?

          • 2. Re: can I put something else then strings into the calendarD
            Mario Balaban Newbie

            Hello,
            I tried to put a vector of NameClassPair instances just for experiment but I get the error:

            javax.el.PropertyNotFoundException: /agenda.xhtml @88,44 value="#{record.name}": Property 'name' not found on type java.lang.String

            even if there is the "name" property in the elements of the vector.


            here is the code of myDataModel

            public class myDataModel implements CalendarDataModel {
             @Override
             public CalendarDataModelItem[] getData(Date[] arg0) {
             if (arg0 == null) {
             throw new IllegalArgumentException(
             "Null date array argument for getData.");
             }
             CalendarDataModelItem[] items = new CalendarDataModelItem[arg0.length];
             for (int i = 0; i < arg0.length; i++) {
             items
             = createDataModelItem(arg0
            );
             }
            
             return items;
             }
            
             private CalendarDataModelItem createDataModelItem(Date date) {
             CalendarDataModelItemImpl item = new CalendarDataModelItemImpl();
             HashMap<String, Object> data = new HashMap<String, Object>();
             FacesContext facesContext = FacesContext.getCurrentInstance();
             ExternalContext externalContext = facesContext.getExternalContext();
             DefinitionManager definitionManager = (DefinitionManager) externalContext
             .getSessionMap().get("definitionManager");
            
            /////////////-----Changed code-------/////////////////////
             Vector listDataModel =new Vector();
             for (int i=0;i <4;i++){
             NameClassPair element=NewClassPair();
             elemetn.setName("Name:"+date.toString());
             listDataModel.add(element);
            }
            ////////////-----Changed code------//////////////////////
            
            
             item.setEnabled(true);
            
            
             data.put("eachDayDataList", listDataModel);
            
            
             item.setData(data);
            
             return item;
             }
            
             @Override
             public Object getToolTip(Date arg0) {
             // TODO Auto-generated method stub
             return null;
             }
            
             public LavoriSchedulatiDataModel() {
             // TODO Auto-generated constructor stub
             }
            
            }


            the xhtml and the other class rests the same. Any suggestions?



            • 3. Re: can I put something else then strings into the calendarD
              Nick Belaevski Master

              Mario,

              I've rechecked page code again. Unfortunately that won't work in that way. Iterational components are not the right ones to use inside calendar. That's because of the way it works: children are rendered for first cell and that and only that data is present on the client to build another cells.

              Possible solution - use JS functions to build what you need:

              <script>//<![CDATA[
               function cookData(data) {
               var s = '';
               for ( var i = 0; i < data.length; i++) {
               s += data.data;
               if (i != data.length) {
               s += "<br /> ";
               }
               }
              
               return s;
               }
               //]]></script>
              
               <rich:calendar popup="false" mode="ajax" dataModel="#{calendarDataModel}">
               <h:outputText value="{day} - {cookData(data)}" />
               </rich:calendar>
              


              package org.richfaces;
              
              import java.util.Date;
              import java.util.HashMap;
              import java.util.Map;
              import java.util.Random;
              import java.util.UUID;
              
              import org.richfaces.model.CalendarDataModel;
              import org.richfaces.model.CalendarDataModelItem;
              
              public class CalendarDataModelImpl implements CalendarDataModel {
              
               public CalendarDataModelItem[] getData(Date[] dateArray) {
               CalendarDataModelItem[] items = new CalendarDataModelItem[31];
              
               for (int i = 0; i < items.length; i++) {
               final int j = i;
               items = new CalendarDataModelItem() {
              
               public Object getData() {
               Map[] maps = new Map[new Random().nextInt(4) + 2];
               for (int j2 = 0; j2 < maps.length; j2++) {
               maps[j2] = new HashMap<String, Object>();
              
               maps[j2].put("data", UUID.randomUUID().toString());
               }
              
               return maps;
               }
              
               public int getDay() {
               // TODO Auto-generated method stub
               return 0;
               }
              
               public String getStyleClass() {
               // TODO Auto-generated method stub
               return null;
               }
              
               public Object getToolTip() {
               // TODO Auto-generated method stub
               return null;
               }
              
               public boolean hasToolTip() {
               // TODO Auto-generated method stub
               return false;
               }
              
               public boolean isEnabled() {
               // TODO Auto-generated method stub
               return true;
               }
              
               };
               }
              
               return items;
               }
              
               public Object getToolTip(Date date) {
               // TODO Auto-generated method stub
               return null;
               }
              
               }
              


              • 4. Re: can I put something else then strings into the calendarD
                Dhrubojyoti Kayal Newbie

                All data are null or Object type
                How can you get values from it ... i get it all undefined

                • 5. Re: can I put something else then strings into the calendarD
                  Dhrubojyoti Kayal Newbie

                  Ok folks here is an workaround that I am using:

                  1> Change your CalendarDataModelItemImpl.getData method to pass JSON data as shown below :

                  
                  /* (non-Javadoc)
                   * @see org.richfaces.component.CalendarDataModelItem#getData()
                   */
                   public Object getData() {
                   JSONSerializer serializer = new JSONSerializer();
                   String temp = serializer.serialize(data);
                   System.out.println("temp="+temp);
                   return temp;
                  
                   }
                  
                  Ok friends let me know if this helps
                  
                  
                  
                  


                  Note I am using FlexJSON library available here - http://flexjson.sourceforge.net/

                  2> Here is my setData method
                   /**
                   * @param data the data to set
                   */
                   public void setData(Object data) {
                   this.data = data;
                   }
                  
                  


                  Its the normal setData which accepts some Object. In this case I set a List of Event objects for that particular date. I retrieve these events from database and set it in CalendarDataModelImpl.getData by calling the above setData method.

                  3> Now you need to parse this JSON data. For this I am using Prototype Javascript library - http://www.prototypejs.org/learn/json

                  4> Add a custom Javascript method to parse this JSON data as shown below :
                  <script>
                   //<![CDATA[
                   function displayEvents(data) {
                  
                   var jsonData = data.evalJSON();
                   var dataLen = jsonData.length;
                   var s = '';
                  
                   for ( var i = 0; i < dataLen; i++) {
                   alert(jsonData.subject);
                   s += jsonData.subject;
                   if (i != dataLen) {
                   s += "<br /> ";
                   }
                   }
                   return s;
                   }
                   //]]></script>
                  


                  5> Finally the Rich faces calendar markup in organizer mode is shown below:

                  
                  <rich:calendar value="#{calendarbean.selectedDate}"
                   popup="false" showApplyButton="false"
                   cellWidth="90px" cellHeight="70px"
                   id="organizer" mode="ajax"
                   toolTipMode="single"
                   showWeeksBar="false"
                   dataModel="#{calendarbean.calendarModel}"
                   showFooter="false" >
                  
                  
                   <a4j:support event="onchanged" reRender="selectedDt"/>
                  
                   <a4j:outputPanel layout="block" id="cell" >
                  
                   <h:panelGrid columns="1">
                   <h:outputText value="{day}" style="align:center"/>
                  
                   <h:outputText value="{displayEvents(data)}" />
                  
                   </h:panelGrid>
                  
                  
                   </a4j:outputPanel>
                   </rich:calendar>
                  


                  • 6. Re: can I put something else then strings into the calendarD
                    Nick Belaevski Master

                    Hi,

                    I've just checked witj list of objects. It works without any external JSON manipulations. Can you please provide more info about data you use (list of events; what event is?) and RF version?

                    • 7. Re: can I put something else then strings into the calendarD
                      Eric H Novice

                      I ran into the same problem. It would be nice for us who want to use the calendar as an organizer view to be able to treat the calendar cells sort of like a rich:column or something.

                      I'm going to solve it not by using JS to render into the cells, but just write a method that create a List of values, and then render it all with a h:panelGrid columns="7"

                      • 8. Re: can I put something else then strings into the calendarD
                        Mario Balaban Newbie

                        I thank everybody for the interest. Anyway there is no need to use any additional java script to obtain similar results to those described earlier. Just concatenate the strings with string events for that day with like this :

                        private CalendarDataModelItem createDataModelItem(Date date) {
                         CalendarDataModelItemImpl item = new CalendarDataModelItemImpl();
                         HashMap<String, Object> data = new HashMap<String, Object>();
                        
                        >>>>>>-----Changed code-------<<<<<<<<<<<
                         String listDataModel ="";
                         for (int i=0;i <4;i++){
                         listDataModel=+"Event "+i+" :"+date.toString()+"<br/>";
                         }
                        >>>>>>>-----Changed code------<<<<<<<<<<<
                        
                        
                         item.setEnabled(true);
                        
                        
                         data.put("eachDayDataList", listDataModel);
                        
                        
                         item.setData(data);
                        
                         return item;
                         }
                        


                        The xhtml page:
                        <rich:calendar popup="false" mode="ajax" dataModel="#{calendarDataModel}">
                         <h:outputText value="{day} - {data.eachDayDataList}" />
                         </rich:calendar>
                        



                        But this is mixing logic with presentation and repeating I'd like to use some thing clickable in each day cell (dataTable,dataList.. similar to google calendar or the one in the teamwork project). For the moment I will use this trick with a modalPanel showing on cell click event.