5 Replies Latest reply: May 22, 2013 11:21 AM by Jeet_A RSS

    Using Contextual Events for <af:commandToolbarButton ...>

    DzmitryP
      Hi all,

      I am using 11.1.1.7.0 jdev and I can't update to some newer version.

      I need to fire an event in one region, and perform some actions according to it in other one. I want to use ContextualEvent functionality as it was described in here . All seems clear, but I stuck in how to declare Contextual event.

      I have a <af:commandToolbarButton ...> element to produce contextual event, I can't change it to another element. "af:commandToolbarButton" doesn't have Behaivor - ContextualEvents inside-tab to declare a Contextual event. May I need to specify it in other way, for example using a actionListener="#{viewScope.BeanName.callToEventProducer}" and perform attempt to rise contextual event programmatically?


      in my code I have:
      <af:commandToolbarButton ... actionListener="#{BBean.commandUndoRedo}"/>
      and in bean code:
          public void commandUndoRedo(ActionEvent actionEvent) {
              BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
              JUEventBinding eventBinding = (JUEventBinding) bindings.get("undoRedoEvent");
              ActionListener al = (ActionListener)eventBinding.getListener();
              al.processAction(actionEvent);
          }
      and in taskFlow page def:
        <bindings>
          <eventBinding Listener="javax.faces.event.ValueChangeListener" id="undoRedoEvent">
            <events xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
              <event name="undoRedoPublisherEvent"  eventType="Action Event"/>
            </events>
          </eventBinding>
        </bindings>
      and when I try to find this event in other task flow in pageDef - Bindings - ContextualEvents - Subscribers -

      I don't see any 'undoRedoEvent' or 'undoRedoPublisherEvent'

      Am I doing all right?

      Thank you.
        • 1. Re: Using Contextual Events for <af:commandToolbarButton ...>
          Jeet_A
          Hi,


          Please refer to forum,

          ADF Contextual Event
          You need to create anonymous provider "*"
          (Check Frank's comment)
              <event name="*">
                <producer region="eventBinding"></producer>
              </event>
          and in its subsciber you can select your actual event.
            <eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
              <event name="undoRedoEvent">
                <producer region="XXXXXXXX.eventBinding">
                  <consumer region="" handler="YourHandler"/>
                </producer>
              </event>
            </eventMap>
          Thanks,
          Jit
          • 2. Re: Using Contextual Events for <af:commandToolbarButton ...>
            DzmitryP
            I looked at your posts, but I have a little bit different situation.

            I have a Page 'Home'. Inside a 'Home' I have a bounded task flow 'A'. Inside the bounded task flow 'A' I have dynamic region 'B'. This dynamic region can be switched to 'B1' or 'B2'. Inside a 'B1' or 'B2' I have a same bounded task flow 'D'. I making an operation inside a region 'A':

            In this bounded task flow 'A' I generating an event in response of this operation (call it programmaticaly):
                <eventBinding Listener="javax.faces.event.ActionListener" id="undoRedoEvent">
                  <events xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
                    <event name="undoRedoPublisherEvent" eventType="Action Event"/>
                  </events>
                </eventBinding>
            , then I want region 'D' to refresh a table in response to this action. Note that region 'D' is inside a dynamic region: 'B1' or 'B2'

            As far as I understand, I need to edit event map for parent - 'Home' region. I expect that for now this event will be accessible for all child regions. Even this is not a direct child and they are in dynamic regions.

            Having the chain like:
            'Home' - 'regionA' - '(dynamic region)BX' - 'C'

            when I am throwing event in 'regionA' I want this event can be heard in region 'C'

            and registering it like
              <eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
                <event name="*">
                  <producer region="regionA">
                    <consumer region="" handler="*"/>
                  </producer>
                </event>
              </eventMap>
            Means that every event came from 'regionA' will be propagated to all the child regions.
            But it is not.

            Playing with events recently I found that I can achieve expected functionality in some strange case:
            For example I making a producer consumer pair in context of only 'regionA', means, when I call to bounded methodCall for DataControl, even this method is nothing to do (empty implementation), table in region 'C' got refreshed. That looks like throwing a Contextual Event causing all the 'regionA' refresh itself.

            But I don't think I can use such shamanic implementation in production.

            Personally for me, looks like Oracle implementation of this Contextual event is confused for complex cases.

            Spend some time investigating it, I think it would be better to find another way to handle refreshes.
            • 3. Re: Using Contextual Events for <af:commandToolbarButton ...>
              Jeet_A
              Hi,

              You can create Event Producer from A
                <eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
                  <event name="*">
                    <producer region="regionA">
                      <consumer region="" handler="handleRefresh"/>
                    </producer>
                  </event>
                </eventMap>
              And inside Consumer handler you can get handle of Region C bean (If it is different from A) and refresh only that part.

              eg.
              this would be your consumer method(Create Class + Create Data Control + Add as Method Action on jsff)
                  public void handleRefresh(Object payLoad){
                           FacesContext fctx = FacesContext.getCurrentInstance();
                      
                      ELContext elctx = fctx.getELContext();
                      ValueExpression valExpr =
                          fctx.getApplication().getExpressionFactory().createValueExpression(elctx,
                                                                                             "#{backingBeanScope.backing_<YourbeanName>}",
                                                                                             YourBeanName.class);
                      YourBeanName bean = (YourBeanName)valExpr.getValue(elctx);
                      bean.refreshT1();
                      
                  }
              You can check
              http://www.jobinesh.com/2010/11/triggering-navigation-from-contextual.html
              http://www.jobinesh.com/2009/07/programmatically-publishing-contextual.html

              Thanks,
              Jit
              • 4. Re: Using Contextual Events for <af:commandToolbarButton ...>
                DzmitryP
                Thank you, now I got it.

                I am using: this is to register event binding for page definition file (producer task flow):
                  <bindings>
                    <eventBinding id="undoRedoBinding"
                                  Listener="javax.faces.event.ActionListener">
                      <events xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
                        <event name="undoRedoEvent" eventType="Action Event"/>
                      </events>
                    </eventBinding>
                  </bindings>
                this method is invoking action event (inside the event produser's bean):
                    public void fireUndoRedoEvent(ActionEvent actionEvent){
                       BindingContainer bindingContainer = BindingContext.getCurrent().getCurrentBindingsEntry();  
                       JUEventBinding eventBinding = (JUEventBinding)bindingContainer.get("undoRedoBinding");         
                       ActionListener actionListener = (ActionListener)eventBinding.getListener();  
                       actionListener.processAction(actionEvent);
                    }
                this is registration in child region (region C inside bounded dynamic task flow, who's region is inside producer's region)
                  <bindings >
                    <methodAction id="handleUndoRedoRefresh"
                                  InstanceName="UndoRedoHandler.dataProvider"
                                  DataControl="UndoRedoHandler" RequiresUpdateModel="true"
                                  Action="invokeMethod" MethodName="handleUndoRedoRefresh"
                                  IsViewObjectMethod="false"/>
                  </bindings>
                  <eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
                    <event name="undoRedoEvent">
                      <producer region="*">
                        <consumer region="" handler="handleUndoRedoRefresh" handleCondition=""/>
                      </producer>
                    </event>
                  </eventMap>
                Just one trouble - when I am opening 'Contextual events' - 'Suscribers' for overview of page definition file and attempt to find event from parent region - I don't see any, but registering it manually through xml editor - seems 'ok'.

                Thank you.
                • 5. Re: Using Contextual Events for <af:commandToolbarButton ...>
                  Jeet_A
                  Hi,

                  Yes, i too didnt find declarative way to add event raised on child page so follow same thing which you did.

                  Inside Page Def below Bindings
                  <bindings/>
                    <eventMap xmlns="http://xmlns.oracle.com/adfm/contextualEvent">
                      <event name="*">
                        <producer region="*">
                          </producer>
                      </event>
                    </eventMap>
                  </pageDefinition>
                  Once we have * we can alter both Publisher and subscriber.

                  Thanks,
                  Jit