1

Today, i was solving a small problem in JSF. Actually, i have an InputText on my xhtml page with readyOnly attribute set to true.Requirement was on click of a boolean checkbox, i should make the input text editable, means readyOnly false. The code somewhat seemed like this.

  <div class="div-form-col" >
            <h:outputLabel value="#{msgs.violationAmount} " for="violationAmt" />

      <h:inputText value="#{outpassMBean.violationWebDTO.violationAmount}" id="violationAmt" readonly="true"/>

    </div>

<div class="div-form-row">
                      <div class="div-form-col">
                          <h:outputLabel value="#{msgs.violationExemptionApplicable} " for="violationExempted" />
                          <h:selectBooleanCheckbox value="#{outpassMBean.violationWebDTO.violationExemptionApplicable}" id="violationExempted" onchange="makeViolationAmountEditable(this);">
                          </h:selectBooleanCheckbox>

                      </div>
                  </div>

The script of that method was given as below :-

function makeViolationAmountEditable(id){
  alert("Ben");
  document.getElementById('violationAmt' ).readOnly=false;
  alert("Done");
}

Now my first problem was, if i am editing the value in the text field, how i can update the value of violationAmt in backing bean. What can be the best possible way? As i am using PrimeFaces, i came across concept remoteCommand. So here is what i added.

<p:remoteCommand name="makeViolationAmountEditableOnServer" action="#{outpassMBean.makeViolationAmountEditable}" update="amountPanelApplicant"/>

The method at the backing bean level was something like this

public void makeViolationAmountEditable(){
//Set updated value 
setUpdatedViolationAmount(violationWebDTO.getViolationAmount());
//Some other code.
}

Problem was that, whenever this code was running, the violation amount in violationWebDTO was the old one, not the one which i was entering after making the input field editable. Though i saw in firebug the updated value was part of request but in the backing bean, however still old value was getting referred. I don't understand why?

My senior told me, you are updating value of readOnly on client side not server side, and updated my code something like this.

<p:outputPanel id="amountPanelApplicant">
          <p:outputPanel  rendered="#{outpassMBean.violationWebDTO.violationForCmb eq 2 and outpassMBean.violationWebDTO.isViolationExists}">
              <p:outputPanel styleClass="div-form twoCol">
                  <div class="div-form-row">
                      <div class="div-form-col" >
                          <h:outputLabel value="#{msgs.violationAmount} " for="violationAmt" />

                          <h:inputText value="#{outpassMBean.violationWebDTO.violationAmount}" id="violationAmt" readonly="#{outpassMBean.violationAmtEditable}">

                          </h:inputText>

                      </div>

                      <div class="div-form-col">
                          <h:outputLabel value="#{msgs.outPayTot} " for="totalViolationAmount" />
                          <h:outputLabel styleClass="readOnly" value="#{outpassMBean.violationWebDTO.totalViolationAmount}" id="totalViolationAmount" />
                      </div>
                  </div>

              </p:outputPanel>

              <p:outputPanel styleClass="div-form twoCol" rendered="#{outpassMBean.outpassApplication.applicationSubType.id eq 2 }" >
                  <div class="div-form-row">
                      <div class="div-form-col">
                          <h:outputLabel value="#{msgs.violationExemptionApplicable} " for="violationExempted" />
                          <h:selectBooleanCheckbox value="#{outpassMBean.violationWebDTO.violationExemptionApplicable}" id="violationExempted" onchange="makeViolationAmountEditableOnServer();">
                          </h:selectBooleanCheckbox>
                          <p:remoteCommand name="makeViolationAmountEditableOnServer" action="#{outpassMBean.makeViolationAmountEditable}" update="amountPanelApplicant"/>

                      </div>
                  </div>
              </p:outputPanel>
</p:outputPanel>

public void makeViolationAmountEditable(){
    if(logger.isDebugEnabled()){
      logger.debug("Inside makeViolationAmountEditable...");
    }
    //setting violation amount editable flag
    setViolationAmtEditable(false);

    //Preserving original and total amount.
    setOriginalViolationAmt(violationWebDTO.getViolationAmount());
    setOriginalTotalViolationAmount(violationWebDTO.getTotalViolationAmount());

  }

In the above updated code, no javascript called. The readyOnly value is set to true and false from the backing bean itself. After this update, basically the new edited value was updated in the violationWebDTO.

Can someone explain? Why not in the first snapshot? It's not a complete code but i tried to explain the confusion. Any pointers would be helpful.

benz
  • 4,561
  • 7
  • 37
  • 68
  • In future questions, please try to post **only** the relevant code. Surely the problem doesn't disappear when you remove those `
    `, ``, etc tags. Just keep them out then!
    – BalusC Feb 19 '14 at 19:22
  • @BalusC, sure i will definitely use the guidelines provided by you. I am just understanding the answer and i will update you if i am finding more confusions. – benz Feb 19 '14 at 19:28

1 Answers1

2

This is JSF's safeguard against tampered/hacked requests wherein the enduser uses client side languages/tools like HTML or JS to manipulate the HTML DOM tree and/or HTTP request parameters in such way that the outcome of JSF's disabled, readonly or even rendered attribute is altered.

Imagine what would happen if the JSF developer checked an user's role in such a boolean attribute against the admin role like so disabled="#{not user.hasRole('ADMIN')}" and a hacker manipulated it in such way that it isn't disabled anymore for non-admin users. That's exactly why you can only change the mentioned attributes (and the required attribute and all converters, validators, event listeners, etc) on the server side.

This can however be solved in a simpler manner without the need for an additional property, without the <p:remoteCommand> and the additional bean method.

<h:inputText id="violationAmount" ... readonly="#{makeViolationAmountEditable.value}" />
...
<h:selectBooleanCheckbox binding="#{makeViolationAmountEditable}">
    <f:ajax render="violationAmount" />
</h:selectBooleanCheckbox>

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • i have a confusion, when you say readonly="#{makeViolationAmountEditable.value}", are you calling the backing bean method. What is this value referring to? Does binding attribute, bind the boolean checkBox to a backing bean method? – benz Feb 19 '14 at 19:27
  • 1
    This is in detail explained in 2nd "See also" link – BalusC Feb 19 '14 at 19:28
  • 1
    Another related answer with more specific explanation as to the checkbox with binding: http://stackoverflow.com/questions/17167377/jsf-checkbox-listener/17170220#17170220 – BalusC Feb 19 '14 at 19:32
  • i am understanding the explanation on component binding. Finding it little confusing, and i am gonna update my comment if i don't understand it. You always provide great answers. – benz Feb 19 '14 at 19:34
  • Another one which handles the binding-without-bean-property part: http://stackoverflow.com/questions/8168302/jsf-component-binding-without-bean-property – BalusC Feb 19 '14 at 19:37
  • the binding attribute simply meant that we get a complete component rather than just it's value. We can then access its different attributes. My question is, how would we declare makeViolationAmountEditable in backing bean? Secondly, how would render work in f:ajax? – benz Feb 19 '14 at 19:50
  • 1
    1) There you use component's `value` attribute for. 2) Sorry? Is `` *also* new to you? I understand that `binding` is as least understood feature usually not explained in depth, but `` should be already covered in the 1st chapters of a sane JSF2 book/tutorial. It just fires an ajax request on the default HTML DOM event and the `render` attribute tells JSF what components to re-render (update) in the response. This way the checkbox component's value is re-evaluated in `readonly` attribute. – BalusC Feb 19 '14 at 19:52
  • No, my question is do we need to declare HtmlBooleanCheckBox as backing bean property? Secondly, will f:ajax render would work with component binding? I am sorry, my question wasn't that clear. I do understand how f:ajax and render works. – benz Feb 19 '14 at 19:55
  • 1
    In other words, you haven't even tried the given code? The code is just complete and as-is, as usual in my answers. Aren't you just astonished by its simplicity? How it works is already in depth explained in the given links. To continue on the last given link, the "view build time" versus "view render time" is in turn in depth explained in http://stackoverflow.com/a/3343681 – BalusC Feb 19 '14 at 19:58
  • actually, i can't try at this point as production database is at office. I would try it tomorrow and revert back to you if it works or not. I am definitely astonished as its short and cleaner. I would definitely give it a try and update you. – benz Feb 19 '14 at 20:01
  • i just tried your code and it works like magic. Thanks a ton for your feedback. I went through all links and understood a lot. Your answers are always complete, comprehensive and full of insights. You are a great asset. Thank you so much. – benz Feb 20 '14 at 05:55