2

I've seen a few articles here trying to bind computed fields but my preferred solution; getComponent is just not working for me. I'd rather not have hidden "real" fields. Here's what I have. A computed VAT Tax percentage field called VP

<xp:text escape="true" id="VP" value="#{FInvoiceDoc.VP}" style="text-align:right">
 <xp:this.converter>
  <xp:convertNumber pattern="0.00"></xp:convertNumber>
 </xp:this.converter>
</xp:text>

Here is one of the calculations where I set the value of this field;

XSP.getElementById("#{id:VP}").innerHTML = tmp.toFixed(2);

tmp calculates correctly, VP displays the correct expected value on the page.

Then in my querySaveDocument event, I do the following

var VP = getComponent("VP").getValue();
FInvoiceDoc.replaceItemValue("VP",VP);

and what gets stored is a Null value. I've even confirmed that the VP variable is null by doing a "Print (VP)" command after setting the VP variable then checking the log. There's got to be something I'm missing.

Community
  • 1
  • 1
cjames728
  • 193
  • 1
  • 12

3 Answers3

4

At page submit you don't get a computed text field's value back to server as it is read only.

You are looking for a solution where you can:

  • show a document's field in read mode
  • set new values to this field on client side with CSJS
  • save the value back to document's field on submit

The first two points working already with your solution.

The third point you can achieve with adding an input text field "VPdoc" which is bound to your document's field "VP" and hidden with style="display:none".

<xp:inputText
    id="VPdoc"
    value="#{FInvoiceDoc.VP}"
    style="display:none">
    <xp:this.converter>
        <xp:convertNumber pattern="0.00"></xp:convertNumber>
    </xp:this.converter>
</xp:inputText>

At submit copy the current value (innerHTML) from computed text field "VP" to input text field "VPdoc" using the following CSJS code in submit button:

<xp:this.script><![CDATA[
    XSP.getElementById("#{id:VPdoc}").value = 
                                XSP.getElementById("#{id:VP}").innerHTML
]]></xp:this.script>

This way the value which was set on client side to field "VP" is saved to document.

Knut Herrmann
  • 30,880
  • 4
  • 31
  • 67
  • That did the trick! As a matter of fact, this has caused me to rethink all those red-hidden fields I keep at the top of the doc. You rock Knut! – cjames728 Apr 17 '14 at 11:38
0

You do NOT assign a value, but replace the html- representation by some html code. With that you simply break the element and kind of "convert" it to a stupid div (sorry, don't know how to explain better)...

Never mess around with the frontend: the element is bound to an item in your document. Modify that value, and the element representing it will represent the change.

And: you do not need that lines of code in querysavedocument to save back the value... This will be done automatically, that's what binding (value property of element) is for...

Tode
  • 11,795
  • 18
  • 34
  • 1
    I suppose this is the frustrating thing about this. Regular fields can be updated with a client-side XSP.getElementByID("Blah").value = BlahBlah works fine and will update the back-end doc, but with computed fields, you're forced to use XSP.getElementByID("Blah").innerHTML = BlahBlah which won't update the back-end. I'm avoiding back-end commands during the time the user edits the document because they cause *really* ugly page refreshes. (Even partial refreshes make my eyes bleed.) I like living in the front-end because at least there's a debugger. (of sorts...) – cjames728 Apr 16 '14 at 22:15
  • 1
    Remember that you can restrict the target of partial refreshes. For example, the `onChange` of a combo box can refresh just that combo box if its value shouldn't impact the rendering of other components but you still want the server to know immediately that its value changed. In this case, you have one field whose value is dependent upon another. So set the refresh target of the event to refresh only that one field. – Tim Tripcony Apr 17 '14 at 08:08
  • Also, if your concern is debugging, get Mark Leusink's debug toolbar, available on OpenNTF -- http://www.openntf.org/main.nsf/project.xsp?r=project/XPage%20Debug%20Toolbar – David Navarre Apr 17 '14 at 13:44
0

Perhaps, instead of manipulating the innerHTML, you used

getComponent("VP").setValue(tmp.toFixed(2));

Would that work? You'd be setting the value of the component then, I think.....

David Navarre
  • 1,022
  • 10
  • 27
  • I don't want to set the value with a back-end command until the person is finished updating the document. Back-end updates during the edit result in page refreshes which I *really* want to avoid. They're ugly as sin! – cjames728 Apr 16 '14 at 21:56
  • @cjames728 Updating it on the back end does not result in a page refresh unless you tell it to refresh. – David Navarre Aug 05 '14 at 14:57