0

I have a JSF application in which I have an combobox like this.

<script type="text/javascript" defer="defer">
  <!--//--><![CDATA[//><!--
    helpKey = 'APPLICATION_EDIT_DATASOURCE';

    function reapplyStyles() {}

    function selectT(data){
        if(data.status == "begin"){
            $('editForm:selectTypeButton').click();    
        }
    }

   //--><!]]>
</script>

  <h:form id="editForm">
    <h:inputHidden id="id" value="#{applicationObject.objectId}"/>
    <h:inputHidden id="type" value="#{applicationObject.object.type}"/>
    <h:inputHidden id="selectedDSForApp" value="#{applicationObject.selectedDataSourceId}"/>
    <ui:param name="activityDataSource" value="#{applicationObject.selectedDataSourceBean}"/>

    <a4j:outputPanel id="activityDataSourceRulesPanel">
    <h:panelGrid columns="2" columnClasses="padded" rowClasses="padded">

      <h:outputText value="#{msgs.transformation_rule}"/>
      <h:panelGroup>
          <h:selectOneMenu id="dsTransformationRule" value="#{activityDataSource.selectedTransformationRule}"
                           disabled="#{!sp:hasRight(facesContext, 'ManageApplication')}"
                           readonly="#{!sp:hasRight(facesContext, 'ManageApplication')}">
            <f:selectItems value="#{activityDataSource.transformationRules}"/>
          </h:selectOneMenu>
          <ui:fragment rendered="#{sp:hasRight(facesContext, 'ManageRules')}" >
              <input type="button" value="#{msgs.button_ellipsis}" class="ruleEditorBtn"
                     onclick="SailPoint.Rule.Editor.edit($('editForm:dsTransformationRule').value,
                             'ActivityTransformer',
                             $('editForm:refreshActivityDataSourceRulesButton'))" />
          </ui:fragment>
      </h:panelGroup>

      <h:outputText value="#{msgs.correlation_rule}"/>
      <h:panelGroup>
          <h:selectOneMenu id="dsCorrelationRule" value="#{activityDataSource.selectedCorrelationRule}"
                           disabled="#{!sp:hasRight(facesContext, 'ManageApplication')}"
                           readonly="#{!sp:hasRight(facesContext, 'ManageApplication')}">
            <f:selectItems value="#{activityDataSource.correlationRules}"/>
          </h:selectOneMenu>
          <ui:fragment rendered="#{sp:hasRight(facesContext, 'ManageRules')}" >
              <input type="button" value="#{msgs.button_ellipsis}" class="ruleEditorBtn"
                     onclick="SailPoint.Rule.Editor.edit($('editForm:dsCorrelationRule').value,
                             'ActivityCorrelation',
                             $('editForm:refreshActivityDataSourceRulesButton'))" />
          </ui:fragment>
      </h:panelGroup>

      <h:outputText value="#{msgs.activity_data_src_type}"/>
      <h:panelGroup>
        <a4j:outputPanel id="collectorSettings">
          <h:selectOneMenu id="collectorType"
                           value="#{activityDataSource.object.type}"
                           rendered="#{empty activityDataSource.object.id}"
                           disabled="#{!sp:hasRight(facesContext, 'ManageApplication')}"
                           readonly="#{!sp:hasRight(facesContext, 'ManageApplication')}">
                          <!--  onchange="$('editForm:selectTypeButton').click();"> -->
             <f:ajax event="change" 
                    onevent="selectT"
                    execute="@this dsTransformationRule dsCorrelationRule"
                    render="dsTransformationRule dsCorrelationRule"
                    listener="#{activityDataSource.handleCollectorTypeChange}" />
            <f:selectItem itemValue="" itemLabel="#{msgs.select_collector_type}"/>
            <f:selectItems value="#{activityDataSource.collectorTypes}"/>
          </h:selectOneMenu>
          <h:selectOneMenu id="fixedCollectorType" value="#{empty activityDataSource.object.type ? 'None' : activityDataSource.object.type}"
                           rendered="#{not empty activityDataSource.object.id}"
                           disabled="true"
                           readonly="true">
            <f:selectItem itemValue="#{empty activityDataSource.object.type ? 'None' : activityDataSource.object.type}"
                          itemLabel="#{empty activityDataSource.object.type ? msgs.none : activityDataSource.object.type}"/>
          </h:selectOneMenu>
        </a4j:outputPanel>
      </h:panelGroup>
    </h:panelGrid>
    </a4j:outputPanel>

    <a4j:outputPanel id="configSettings">
      <h:messages infoClass="formInfo" warnClass="formWarn" errorClass="formError" fatalClass="formError"/>

      <h:panelGroup  rendered="#{not empty activityDataSource.object.collector}">
        <ui:include src="#{activityDataSource.configPage}"/>
      </h:panelGroup>
    </a4j:outputPanel>
    <h:panelGroup>
      <div class="buttonRow">
        <ui:fragment rendered="#{sp:hasRight(facesContext, 'ManageApplication')}">
          <h:commandButton id="activityDataSourceSave" action="#{activityDataSource.saveAction}" value="#{msgs.button_save}" styleClass="primaryBtn"/>
        </ui:fragment>
        <h:commandButton id="activityDataSourceCancel" action="#{activityDataSource.cancelAction}" value="#{msgs.button_cancel}" styleClass="secondaryBtn"/>
      </div>
    </h:panelGroup>

    <a4j:commandButton id="refreshActivityDataSourceRulesButton"
                       style="display:none"
                       immediate="true"
                       render="activityDataSourceRulesPanel"/>

    <a4j:commandButton id="selectTypeButton" action="#{activityDataSource.selectType}" style="display:none"
                       render="configSettings, collectorSettings"
                       oncomplete="initializeSelectedConfigPage();"/>

  </h:form>

Bean Class

public String getSelectedTransformationRule() {
    if (_selectedTransformationRule == null) {
        ActivityDataSourceDTO dto = getObject();
        if (dto != null)
            _selectedTransformationRule = dto.getTransformationRule();
    }

    return _selectedTransformationRule;
}
public String getSelectedCorrelationRule() {
    if (_selectedCorrelationRule == null) {
        ActivityDataSourceDTO dto = getObject();
        if (dto != null)
            _selectedCorrelationRule = dto.getCorrelationRule();
    }

    return _selectedCorrelationRule;
}

In the above code I have a normal onchange event & an ajax onchange event on combobox element id= collectorType.

Is there any limitation in using two change for same element in JSF.

Also how can I merge first onchange to ajax onchange.

code_fish
  • 3,381
  • 5
  • 47
  • 90

1 Answers1

2

Use onevent attribute of <f:ajax> as follows:

<h:selectOneMenu id="collectorType"
                   value="#{activityDataSource.object.type}"
                   rendered="#{empty activityDataSource.object.id}"
                   disabled="#{!sp:hasRight(facesContext, 'ManageApplication')}"
                   readonly="#{!sp:hasRight(facesContext, 'ManageApplication')}">
     <f:ajax event="change" 
            execute="@this" 
            render="dsTransformationRule dsCorrelationRule"
            listener="#{activityDataSource.handleCollectorTypeChange}" 
            onevent="$('#editForm\\:selectTypeButton').click();"/>
    <f:selectItem itemValue="" itemLabel="#{msgs.select_collector_type}"/>
    <f:selectItems value="#{activityDataSource.collectorTypes}"/>
</h:selectOneMenu>

also notice I've modified the selector '#editForm\\:selectTypeButton' to escape the : in your button's id.

[UPDATE]

Here's what you can do to achieve the scenario we've discussed in the comments:

First to populate both dsTransformationRule and dsCorrelationRule with _selectedTransformationRule and _selectedCorrelationRule respectively, create an initialization method for them, and call it in @PostConstruct method (check Why use @PostConstruct?), so in your bean class you would have something like this:

@PostConstuct
public void init() {
    initRules();
    //include another things you want to be initializaed when this page finishes constructing. 
}

private void initRules() {
    ActivityDataSourceDTO dto = getObject();
    if (dto == null)
        return;

    if (_selectedTransformationRule == null)
        _selectedTransformationRule = dto.getTransformationRule();

    if (_selectedCorrelationRule == null)
        _selectedCorrelationRule = dto.getCorrelationRule();
}

//Let the getters do no dto access, so it won't matter if they're called twice on change
public String getSelectedTransformationRule() {
    return _selectedTransformationRule;
}

public String getSelectedCorrelationRule() {
    return _selectedCorrelationRule;
}

Now your f:ajax can normally execute and render your select menus without fearing to access your DTO layer multiple times

<f:ajax event="change" onevent="selectT"
        execute="@this dsTransformationRule dsCorrelationRule"
        render="dsTransformationRule dsCorrelationRule"
        listener="#{activityDataSource.handleCollectorTypeChange}" />

This way, when handleCollectorTypeChange is invoked, will have both _selectedTransformationRule and _selectedCorrelationRule populated with their last selected values.

On a side note, if you want to get the values of select menus dsTransformationRule and dsCorrelationRule in a validation or conversion phase, or directly via an event listener method that is called before the Update Model Values phase, check this answer that would help you reach the value from the component.

Hopefully this would solve your issue, or at least set you in the right direction.

Community
  • 1
  • 1
Qussay Najjar
  • 561
  • 3
  • 7
  • its working. But i noticed while debugging that method in the bean related to element that I want to render are called twice. How to handle this? – code_fish Apr 11 '14 at 10:40
  • @CODEFISH what is getting called twice exactly ? and what are those elements in your `render` attribute ? – Qussay Najjar Apr 11 '14 at 10:49
  • I have upated my question. These 2 method in bean class class are called twice on change event.The ajax change event is in the element id=collectorType. – code_fish Apr 11 '14 at 13:11
  • @CODEFISH that's expected, because you're evaluating both select menus `dsTransformationRule` and `dsCorrelationRule` twice, in `execute` and `render`. Try using only `render` or are you expecting the values submitted from those drop downs on your ajax change event ? – Qussay Najjar Apr 11 '14 at 13:27
  • Yes that what I need. I wants those two id in 'execute' to be executed first,so that they will populate & get the vale & will provide the data for the ajax call. What should i do? I am new to JSF. Basically i want on selection of collectorType combo box other two combox box i.e. dsTransformationRule & dsCorrelationRule should be populated automatically. And the value of those combobox i get from these 2 bean class method. – code_fish Apr 11 '14 at 13:40