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

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

Related

CSJS Not Updating Computed Field

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.

How to pass bean value to JavaScript before form submit

I am making webpage about ride sharing/selling bus tickets using JSF.
On one particular page, logged users can publish their ad (offering or looking for ride).
They should enter info like: ad title, origin city, destination city, departure time, etc.
What I want is, that users get weather forecast of destination city showed in popup after they hit submit.
This also means I am consuming service like openweathermap.
Basically, I have one h:form and h:commandButton like this:
<h:commandButton value="Publish" action="#{adBean.publishAd}" type="submit" onclick="showPopup()">
</h:commandButton>
The problem is that I don't know how to pass bean value of
<h:inputText value="#{adBean.ad.destinationCity}"/>
to JavaScript method showPopup().
I've tried this, but destinationCity turns out to be null.
<h:commandButton value="Publish" action="#{adBean.publishAd}" type="submit" onclick="showPopup(#{adBean.ad.destinationCity})">
</h:commandButton>
Why is this happening and how can I pass its value to JavaScript code?
It is null because it is put in an attribute (onclick) that is used for javascript. Attributes like these are 'rendered' at the time the page is displayed, not (again) at submission time or other moments. So if it is initialized null at that time, what is transferred from the server to the client is
<button value="Publish" ... onclick="showPopup(null)" />
A quote from #BalusC about this in How to invoke a bean action method using a link? The onclick does not work:
In JSF, only the attributes which interpret the EL expression as a MethodExpression can be used to declare action methods. All other attributes are interpreted as ValueExpression and they are immediately executed when the HTML output is generated by JSF. This covers the onclick attribute, whose value should actually represent a JavaScript function.
The (h:?)inputText on the client-side is rendered as a plain html inputText, so if you want access to its value before submitting (like I suspect you want to), you can do so in the showPopup like you would in plain html/javascript.
How to do this is mentioned in many stackoverflow Q/A so either pick one that suites you best e.g. How do I get the value of text input field using JavaScript?, but make sure to also read How can I know the id of a JSF component so I can use in Javascript

Primefaces dataTable JavaScript Callback on row selection with row number

With RichFaces it is possible to execute a JavaScript function when a single row is selected (via a click on the row) and passing the selected row number as a parameter like this:
<rich:extendedDataTable
rowKeyVar="row"
onRowClick="executeMeOnRowSelection(#{(row})"...>
I need to migrate this to Primefaces. According to this question Primefaces itself does not provide this functionality, but one can use Primefaces Extensions. However, when I try it like this:
<p:dataTable rowIndexVar="row" selectionMode="single">
<pe:javascript event="rowSelect" execute="executeMeOnRowSelection(#{(row})"/>
...it would seem that Primefaces generates a JavaScript callback that does not get the selected row number, but is always called with the first row number (a look at the generated page reveals a hard coded value for the function parameter of the executeMeOnRowSelection).
Edit: To be more precise, the #{row} variable seems to not be evaluated when used directly under the p:dataTable tag. It is correctly resolved when used inside a p:column tag, but both
<pe:javascript event="rowSelect" execute="executeMeOnRowSelection(#{(row})"/>
and, for that matter,
<p:ajax event="rowSelect" oncomplete="alert(#{row});" />
end up with #{row} being replaced with an empty string (both placed as direct children of the p:dataTable tag).
Is there an error in the way I use the pe tag in combination with p:dataTable? Is there an alternative solution?

pass javascript value to asp.net function

the question says it all : i have a linkbutton to which i pass through CommandArgument a value and i need that value to be a javascript value. Thanks!
Edit :
here is my linkbutton tag :
< asp:linkbutton id="prevBut"
runat="server" OnCommand="load_com"
CommandArgument=to_place_javascript_string
Text="previous" />
and the function :
public void load_com(object sender, CommandEventArgs e)
{ //get the string from e and search through the database for something }
i want to pass the name of a photo that is stored in a variable $.galleria.current.
You need to stop for a moment and think about what the LinkButton is actually doing. It's not magic. It's just posting the form for you.
As such, you can...
define an onsubmit handler to stuff that javascript value into a hidden form field
or, replace that LinkButton with a simple <a onclick="dostuff()"> pointing at a function that stuffs your value into a hidden form field and submits the form
or, replace that LinkButton with a simple <a onclick="dostuff()"> pointing at a function that constructs a URL containing ?myvalue=whatever and redirects to it.
There's no reason you need to involve ASP:LinkButton in any of it. If the built-in ASP.NET controls aren't doing what you want. All you need to do is stop using them.
(Incidentally, you'll have a much happier and more productive career in the .NET world if you stop using Microsoft's Rich Controls in favor of their HTML equivalents. Those things are there so that non-programmers can drag/drop their way to unmaintainable websites. Since you're here, we can assume you're not a non-programmer, and are therefore smart enough to ignore the marketing portions of ASP.NET and use the good stuff directly.)
Are you looking to place a string of javascript code in the command argument or a value which can be accessed via javascript?
If you need a value to be accessible via javascript you could put the command argument value in an attribute of the linkbutton <a href="javascript:void(null)" commandArg="value" >Link Text</a> this would make "commandArg" available via jQuery like $('#linkID').attr('commandArg') . You could obviously name that attrubute whatever you need to.

Javascript function results in HTML page reload: why?

Newbie question...
The objective:
I intend to have an HTML text input field as a kind of command line input.
An unordered HTML list shows the 5 most recent commands. Clicking on one of the last commands in this list should populate the command line input text field with the respective command (in order to re-execute or modify it).
An unordered HTML list contains a result set. Clicking on an ID in this list should bring the respective ID into the command line input text field.
In HTML (DHTML):
Works as expected: when clicking on the the link the command line input text field is populated with a recent command.
<li>here would be one of the recent commands</li>
In Javascript file:
Doesn't work as expected: when clicking on the the link the command-line-input-text-field gets populated with the respective value (as it should), BUT then it seems like the full HTML page is being reloaded, the text input field and all dynamically populated lists become empty.
function exec_cmd(cli_input_str) {
// a lot of code ...
// the code that should provide similar behavior as onclick=... in the DHTML example
$('.spa_id_href').click(function(){document.getElementById('cli_input').value = document.getElementById('cli_input').value + this.firstChild.nodeValue;});
}
Now the Question:
Besides a potential Javascript (syntax) error, what could cause the browser to reload the page?
In both cases, you do nothing to cancel the default function of clicking on a link.
In the plain HTML example, the link to the top of the page is followed.
You don't specify what the href attribute for the second example looks like, but whatever it is, it will be followed.
See http://icant.co.uk/articles/pragmatic-progressive-enhancement/ for a good explanation of event cancelling and good event design. See http://docs.jquery.com/Tutorials:How_jQuery_Works for some jQuery specific guidance.
Change
$('.spa_id_href').click(function(){...
to
$('.spa_id_href').click(function(evt){...//notice the evt param
and in the function, call
evt.preventDefault();
It seems that you just follow the link target URL. That is because you do not prevent the default click action:
e.preventDefault(); // `e` is the object passed to the event handler
// or
return false
Alternatively, you can set up a href starting with #, or not use <a> element at all (use <span style="cursor:pointer"> instead) β€” if it’s not a real link of course.
It's basically related to event cancelling...
Try this:
try { (
e || window.event).preventDefault();
}
catch( ex )
{
/* do Nothing */
}
While the other answers here make excellent points about canceling events, you will still run into problems if your JavaScript contains errors which prevent your event-canceling code from being run. (As might be the case if you're, say, debugging your code.
As an additional precaution, I strongly recommend you not use href="#" on links which only trigger scripts. Instead, use the void operator:
...
The reason for this is: when the event is not canceled, the browser will attempt to load the URL supplied by the href attribute. The javascript: "protocol" tells the browser to instead use the value of the accompanying code unless that value is undefined. The void operator exists explicitly to return undefined, so the browser stays on the existing page β€” with no reload/refresh β€” allowing you to continue debugging your script.
This also allows you to skip the entire event-canceling mess for JS-only links (though you will still need to cancel events in code attached to links which have a "fallback" URL for non-JS clients).

Categories