CSJS Not Updating Computed Field - javascript

I very seldom use CSJS, but in this case I'm trying to get it to update a computed field. While the field has the value updated so that I can get to it with an alert, I can't get it to display on the XPage. I've tried using an editable field with Read Only checked, but the data doesn't appear on the XPage with it either.
I'm invoking a CSJS script block and I know you need to refresh to get the change to display, but I've put a panel around the field and tried it with that and a div. Neither produces an error message, but nor does the value display.
I'm using XSP.partialRefreshGet("#{id:remaining}"); right after I set the value. I've tried it with .partialRefreshPost, which doesn't do anything, but then I read in Stephan Wissel's post "Meet the XSP object" that "...For POST the refreshId must point to a form..." and this XPage is not attached to a form. I have also tried using the parameter immediate:true.
I've read Teresa Monahan's article "Client Side JavaScript Libraries in XPages", Serdar Basegmez's "10 Mistakes You and Every XPages Developer Make", anything I can find on the web, as well as the "Mastering XPages" book. I know this shouldn't be that difficult, so I believe I'm just missing something (probably stupid).
Per the above, neither the XPage, nor the particular field is bound to any form. This is on the first tab of a tabbed table, and is just displaying a calculated value. The value does not need to be saved anywhere.
I am invoking the function in my agent by using onChange="Testing()" in dijit/form/ComboBox selections because I want the tiny boxes and again, I don't need the field values after the selections have been made.
Here is the simple text in the script block:
function Testing(){
XSP.getElementById("#{id:remainingPts}").value = "100";
var rewards = XSP.getElementById("#{id:numOfRewards1}").value;
alert("rewards: " + rewards);
XSP.partialRefreshGet("#{id:remaining}");
}
And here is what the field looks like:
<xp:panel id="remaining">
<xp:text escape="true" id="remainingPts" value="0">
</xp:text>
</xp:panel>
What am I doing incorrectly?

I think xp:text is rendered as a <span> tag, in which case you need to set .innerHtml() instead of .value(). See How do I change the text of a span element in JavaScript. You won't need to refresh to see the change.

Related

Where does Blazor store form data?

Interestingly, some input elements of Blazor Forms don't have the data stored in HTML as value (attribute) of the input-field. The fields doesn't even have a value attribute!
When I inspect and use 'Store as global object' functionality in chrome and check the value of the element in console (temp1.value), I can see the value.
I'm wondering where this value is being stored in the browser.
The value attribute is not set by changing the DOM's .value property.
Consider the following minimal example:
<input id=time>
<script>setInterval("time.value = new Date()", 1000);</script>
<input type=button onclick=alert(time.value) value=read>
You can inspect the clock and see that there's never a value attribute, yet the input's value property can be both setted and getted by script.
Thus, the value of the form input in your question can come from almost anywhere. It's likely embedded deep inside the other library support code that makes it easy to shuttle data back and forth, but that's speculation on my part. It's a JS variable of some sort, that much we know. The main thing is that attributes are not needed when making heavy use of JS.

xpage getComponent always returns null even when variable is declared and initialized

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.
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.
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...
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.....

Can javascript "show" a field's input value?

I have a field that shows a value 4 in the UI. The site is built using a complex build process that I do not totally understand (I work as part of a team).
When I inspect the HTML for the field, I don't see the value 4.
I am confused about how this might happen. Is it possible that javascript is "showing" the value of the input field?
DOM elements have attributes and properties. The two are not always identical. The web inspector, in general, shows attributes as part of the DOM structure, like.
<input type="text" value="4" />
However, if there is no value attribute, this does not mean that the element has no value. For example, consider the following HTML:
<input type="text" id="test" />
When you load the page, the attribute document.getElementById("test").getAttribute("value") is null, and the property document.getElementById("test").value is "" (empty string). When you enter 4 into the input field, the attribute "value" is still null, but the property value has changed to "4".
Long story short, the web inspector is not obligated to show the value of an input since it is does not always appear in the DOM as an attribute.
yes, you can change the value in javascript. and that is what is happening in your case
document.getElementById("materials_price_1").value = "4";
I am not sure what the issue is.
If the input contains a 4 that does not mean the attribute value will be equal to 4.
It just means that the value of the input is 4.
Just check value of this field with JavaScript:
document.getElementById('materials_price_1').value;
Or with jQuery:
$('#materials_price_1').val();
Yes, if you using chrome you can in inspect element stand with the mouse on the elemnet in 'Elements' tab and right click.
Now choose 'Inspect DOM Properties' this will open you bottom of the tab the console tab. there you can find the DOM object of your field. open the object and find property value. this is the active value right now
Sure. it happens in the DOM. you can simply make it blank by writing this code in your body tag :
<script>
document.getElementById('materials_price_1').value='';
</script>
just make sure you put the code after your other Javascript codes.

a4j:param not invoking my javascript pointed to by value attribute

I am open to a different way to do this, but what I have seems like it should work from the documentation for RichFaces4 and JSF2.
The user flow is like this:
1) There is a 'Check Out' document link implemented with h:outputLink
2) The user clicks it and gets prompted with a dialog to enter check out comments implemented with rich:popupPanel
3) The user enters comments and clicks 'Continue' Button on the rich:popupPanel implemented with h:link (tried h:commandLink and a4j:commandLink also)
4) A new window pops up with the contents set to the h:link outcome attribute
In my broken case, everything works except when I pass a parameter from h:link
with a4j:param, whose value attribute does not resolve the javascript it points to correctly.
<h:outputLink id="promptForCommentsLink"
onclick="#{rich:component('commentsDlg')}.show();return false;"
value="#"> Check Out </h:outputLink>
<rich:popupPanel id="commentsDlg" modal="true">
<h:inputTextarea id="commentsId"/>
<h:link id="continueLink"
outcome="editorPage" <!-- editor for making changes to document -->
target="_blank" <!-- open in it;s own indow -->
value="Continue Check Out"
onclick="#{rich:component('commentsDlg')}.hide();">
<!-- these params get assignd to backing bean properties -->
<a4j:param name="dataId"
value="#{ithRow.id}" assignTo="#{myController.dataId}"/>
<a4j:param name="checkedOut"
value="true" assignTo="#{myController.checkedOut}"/>
<!-- this one is broken. assigns chars 'document.getElementById('..
to #{myController.checkOutComment} -->
<a4j:param name="checkOutComment"
assignTo="#{myController.checkOutComment}"
noEscape="true"
value="document.getElementById('myForm:dataTable:0:commentsId').value"
/>
</h:link>
</rich:popupPanel>
I was thinking maybe
document.getElementById('myForm:dataTable:0:commentsId').value
didn't point to what I typed into the textarea, but by putting another button on the dlg and pointing it's onclick to the same element id, it did indeed alert me with what it typed.
When I stop on the server side view scoped myController.setCheckOutComment(String s) method, it gets passed the string "document.getElementById('myForm:dataTable:0:commentsId').value"
According to RF4 documentation:
The a4j:param tag can be used with non-Ajax components in addition to Ajax components. This includes components which are working through the GET request, such as the h:link
and
Variables from JavaScript functions can be used for the value attribute. In such an implementation, the noEscape attribute should be set to true. Using noEscape="true", the value attribute can contain any JavaScript expression or JavaScript function invocation, and the result will be sent to the server as the value attribute.
Since I seem to be playing by the jsf/rf4 rules, I thought this would be okay.
One thing to note, if I use a4j:commandLink instead of h:link, it does indeed
send the result of javascript evaluated, however, that breaks the opening in its own window
and a few other issues.
Any thoughts on what might be happening, or even a better way to do this?
You could use a a4j:jsFunction with the parameters you need. Then call that function from the onclick in the h:link tag like setParams(#{ithRow.id}, true). Problem remain that you can't pass the value as a parameter to the javascript function. You could though use 'execute' to save the value of the inputArea to a backing bean and let the backend handle the value.
So yes, I would do it differently. I think you could handle the two other params at the backend and I would use 'execute' to store the value of the inputArea.
MAG,
Milo van der Zee

Setting the value of h:outputText using Javascript

I have a JSF output text as shown below:
<h:outputText id="totalCount" value="#{myBean.totalCount}" />
And within my javascript- which is being called from a h:selectOneMenu, I am trying to calculate the count and set it.
var total = <some calculation is done>;
document.getElementById("myForm:totalCount").value=total;
I verified that the value was being set by adding an alert, but this was not reflecting in the page. Further noticed that outputtext was being rendered as a SPAN HTML tag.
So, will it not work in a Javascipt? Any suggestions?
Thanks for anyone who can help me.
This would rather be "innerHTML" than "value" in case of spans. The problem is though even if you update it on the client side, value won't be submitted to the server and will be lost on the nearest refresh. It would be safer then to add f:ajax behaviour to your menu and update value there.

Categories