11 Replies Latest reply on Sep 26, 2008 5:29 PM by seamnewbie

    Custom RichFaces Component Tutorial?

      Ok, here is my problem. My web app needs a calendar component that has the ability to disable the selection of certain dates. Ideally I would like to pass the component a list of date objects and let it do the worrying.

      After searching for hours and hours and researching different component libraries, I haven't found anything that works.

      My last resort attempt is to create my own custom component based off of the RichFaces calendar control. I'm pretty sure this is possible, but are there any tutorials to set me in the right direction? I've never made a custom component before.

      Thanks,

      Kevin

        • 1. Re: Custom RichFaces Component Tutorial?
          ilya_shaikovsky

          b.t.w. it's possible with our calendar out-of-the-box.

          read about calendar dataModel.

          • 2. Re: Custom RichFaces Component Tutorial?

            ya, I started reading about that last night. I hadn't looked at the RichFaces demo site since 3.2.1 and it didn't have any examples of that.

            Does anyone know if there are more examples of caledarDataModel? The one on the demo site wasn't very clear to me.

            • 3. Re: Custom RichFaces Component Tutorial?
              shadowcreeper

              Here is something that I have been using... Very simple, just create a couple of functions, most can return null...

               public class MyCalendarDataModel
               implements CalendarDataModel
               {
              
               public CalendarDataModelItem[] getData ( final Date[] dates )
               {
               final CalendarDataModelItem[] dataModelItems = new CalendarDataModelItem[dates.length];
               for( int i = 0; i < dates.length; ++i )
               dataModelItems[ i ] = new MyCalendarDataModelItem( dates[ i ] );
               return dataModelItems;
               }
              
               public Object getToolTip ( final Date date )
               {
               return null;
               }
              
               }
              
               public class MyCalendarDataModelItem
               implements CalendarDataModelItem
               {
              
               @NotNull private final Date m_date;
              
               public MyCalendarDataModelItem ( final Date date )
               {
               m_date = date;
               }
              
               public boolean isEnabled ()
               {
               // the date is only enabled if it is on or between the start/end dates
               return m_inclusiveStartDate != null
               && !m_date.before( m_inclusiveStartDate )
               && ( m_inclusiveEndDate == null || !m_date.after( m_inclusiveEndDate ) );
               }
              
               public String getStyleClass ()
               {
               return null;
               }
              
               public Object getData ()
               {
               return null;
               }
              
               public boolean hasToolTip ()
               {
               return false;
               }
              
               public Object getToolTip ()
               {
               return null;
               }
              
               public int getDay ()
               {
               // TODO: Figure out what this is for...
               final Calendar calendar = Calendar.getInstance();
               calendar.setTime( m_date );
               return calendar.get( Calendar.DAY_OF_MONTH );
               }
              
               }
              


              • 4. Re: Custom RichFaces Component Tutorial?
                shadowcreeper

                oh yeah, m_inclusive*Date should be declared in the MyCalendarDataModel and setup in the constructor

                • 5. Re: Custom RichFaces Component Tutorial?
                  shadowcreeper

                  oops, and the MyCalendarDataModelItem should be a class inside the MyCalendarDataModel (man am I screwing this one up)

                  • 6. Re: Custom RichFaces Component Tutorial?

                    Wow, thanks for all your help. I think I've got it working now.

                    One more question. In the RichFaces example it has a line:

                    item.setStyleClass("rel-hol");


                    Is this just a custom css class or are there some built in styles I could use?

                    • 7. Re: Custom RichFaces Component Tutorial?

                      Ok, sorry I have another question. I've gotten it to work, however it only works for the current month. All other dates are still selectable. How do I make it so that it works for all months?

                      • 8. Re: Custom RichFaces Component Tutorial?
                        shadowcreeper

                        unfortunately, this method requires your calendar to have mode="ajax" (or server, not client)

                        • 9. Re: Custom RichFaces Component Tutorial?
                          ilya_shaikovsky

                          in client mode you should use next possible options

                          1) proload attributes.
                          2) isDayEnabled client side handler

                          • 10. Re: Custom RichFaces Component Tutorial?

                            Huh. Interesting. After I added the mode="ajax" all the correct days are blocked for the current month, but they are also blocked for all the other months. The dates that should be blocked are:

                            Aug 28
                            Sep 4-8
                            Sep 23
                            Oct 2

                            Now for all months the 4-8, and 23 are disabled.

                            Here is my calendar control:

                            <rich:calendar mode="ajax" boundaryDatesMode="none" showWeeksBar="false"
                            dataModel="#{InstanceController.cal}" required="true"
                            value="#{InstanceController.instance.startDate}" datePattern="d/MMM/y" cellWidth="24px" cellHeight="22px" style="width:200px">
                             <a4j:support event="onclick" reRender="endDate" />
                            </rich:calendar>


                            and here is the bit of code that does the disabling:

                            protected CalendarDataModelItem createDataModelItem(Date date) {
                             CalendarDataModelItemImpl item = new CalendarDataModelItemImpl();
                             Calendar c = Calendar.getInstance();
                             Calendar blockedCal = Calendar.getInstance();
                             c.setTime(date);
                             item.setDay(c.get(Calendar.DAY_OF_MONTH));
                             boolean enabled = true;
                             for (int i = 0; i < disabledDates.size(); i++){
                             blockedCal.setTime(disabledDates.get(i));
                             if (blockedCal.get(Calendar.YEAR) == c.get(Calendar.YEAR) && blockedCal.get(Calendar.MONTH) == c.get(Calendar.MONTH) && blockedCal.get(Calendar.DAY_OF_MONTH) == c.get(Calendar.DAY_OF_MONTH) ){
                             enabled = false;
                             }
                             }
                             item.setEnabled(enabled);
                             item.setStyleClass("rel-hol");
                             return item;
                             }


                            the disabledDates variable is a List of Date objects that I want to block.

                            • 11. Re: Custom RichFaces Component Tutorial?

                              Never mind, I found the problem. I copied code from the RichFaces demo site:

                              public CalendarDataModelItem[] getData(Date[] dateArray) {
                               if (dateArray == null) {
                               return null;
                               }
                               if (items==null) {
                               items = new CalendarDataModelItem[dateArray.length];
                               for (int i = 0; i < dateArray.length; i++) {
                               items = createDataModelItem(dateArray);
                               }
                               }
                               return items;
                               }


                              Unfortunately items was only null the very fist time it went into the function, so all of my months had the same disabled days. I just removed the if statement and all is well.

                              Thanks everyone for your help.