In a JSF 2.1 + PrimeFaces 3.2 web application, I need to trigger a JavaScript function after a p:dataTable is loaded. I know that there is no such event in this component, so I have to find a workaround.
In order to better understand the scenario, on page load the dataTable is not rendered. It is rendered after a successful login:
<p:commandButton value="Login" update=":aComponentHoldingMyDataTable"
action="#{loginBean.login}"
oncomplete="handleLoginRequest(xhr, status, args)"/>
As you can see from the above code, I have a JavaScript hook after the successful login, if it can be of any help. The update attribute forces the dataTable's rendered attribute to revaluate:
<p:dataTable var="person" value="#{myBean.lazyModel}" rendered="#{p:userPrincipal() != null}" />
After the datatable is loaded, I need to run a JavaScript function on each row item, in order to subscribe to a cometD topic.
In theory I could use the oncomplete attribute of the login Button for triggering a property from myBean in order to retrieve once again the values to be displayed in the dataTable, but it doesn't seem very elegant.
The JavaScript function should do something with the rowKey of each row of the dataTable:
function javaScriptFunctionToBeTriggered(rowKey) {
// do something
}
The javascript method from the oncomplete attribute is called after the ajax request has finished and thus after the dataTable is loaded.
So you can do the following:
<p:commandButton ... oncomplete="doSomething()"/>
and everything should work fine.
if the page reload, try to call in the document ready:
$(document).ready(function() {
doSomething();
});
Related
I've a legacy ASP.NET application, which I'm trying to modernize. I've a page
MyPage.aspx, and its codebehind MyPage.aspx.cs
I've replaced a custom user control (which does a fileupload) with a custom react component. The react component is working as expected. The old ascx usercontrol had an event handler which is defined in 'MyPage.aspx.cs'as follows.
protected void asyncFile_FileUploaded(object sender, FileUploadedEventArgs e)
//logic to set the uploaded file's name etc for saving.
}
Nowthat the custom control is replaced with an empty DIV, where the react component is being mounted, I'm left with no option to call my C# logic in the 'MyPage.aspx.cs' codebehind file.
I've created a 'CreateProperty.aspx.js' file which is responsible of initializing my react component inside the .aspx page, and below is the contents of this file.
$(document).ready(function () {
if ($('#Myupload').length) {
ReactDOM.render(
<Upload id="pictureupload2"
onChange={onChange}
setBusyState={onBusy}
onUploadSucceeded={onUploadSucceeded}
/>,
document.getElementById("Myupload")
);
}
});
function onChange(e) {
console.log(e);
}
function onBusy(e) {
console.log(e);
}
function onUploadSucceeded(e) {
console.log(e);
}
Once the react component has done the uploading, it calls the function onUploadSucceeded() with my required parameters. But how will I pass that value back to my MyPage.aspx.cs file ?
Please help.
Drop in a standard asp.net button on the form.
Move the code you have/had for the previous event into that button code stub
eg:
protected void asyncFile_FileUploaded(object sender, FileUploadedEventArgs e)
//logic to set the uploaded file's name etc for saving.
}
So, move the above code to the button (style="display:none) to hide it.
AND OF COURSE don't copy the event stub code!!!.
Now, in your js function, do whatever and simply "click" on that button.
The bonus here is you get the badly needed post back when the client side js/ajax runs.
So, you have this:
function onUploadSucceeded(e) {
console.log(e);
document.getElementById('<%= btnOkUpLoad.ClientID %>').click();
So, the above is nice. I mean you could do a js __DoPostBack(); in js, but then you have to pass some parameters, and then client side in the on-load page event, detect the parameters (a pain to wrire up).
So, anytime I want to run code behind from js? Just drop in a asp button, write the code stub for that button, and then client side, use the above ".click()" to run that code. As noted, in MOST cases you want a post back anyway - which is what a asp.net button does for you.
Edit: now I said we want a post back in most cases? Well, I mean when we are all said and done - and thus this button click makes sense. We certainly don't want needless post backs - but when you do, and when you want to run+call a code stub, the this button trick is nice. Just use style="display:none" to hide it from view - but js code can still use the .click() to run (click) the button for you))
I am creating a website using ASP.
I have a web control with an SVG image embedded on it.
<embed id="InletsComponent" class="InletsComponent" src="../images/svg/Inlets.svg" type="image/svg+xml" width="430px" height="200"px/>
On the web control I also have a button.
<input id="Button3" type="button" value="3 into 2" onclick="return ConfigureInlets()" />
The javascript function is:
function ConfigureInlets() {
document.querySelector(".InletsComponent").getSVGDocument().querySelector(".InletsComponentImage").getElementById("I1IN").setAttribute("visibility", "visible");
return;
}
Which basically makes one of the svg elements visible.
The above code works fine.
I now want to extend the code so that instead of the button calling the function I can call the function from the server side. (the reason for this isn't obvious from the example, but basically I want to show and hide svg elements based on a number of checkbox states. It is easier to process all this on the server side and then call the javascript to update the image on the client.).
I have added a RegisterClientScriptBlock to my server side code
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Key", "ConfigureInlets()", true);
The javascript function is being called, but I am getting the following error:
Microsoft JScript runtime error: Unable to get value of the property 'getSVGDocument': object is null or undefined
I believe that this function is being called at a different level to when the button press is calling it. i.e it is being called at the page level and not the web control level. But I am not really sure how to fix it.
try to use jquery to run this function when the document is ready
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Key", "$(function () {ConfigureInlets()});", true);
or use RegisterStartupScript instead of RegisterClientScriptBlock
JSF / PrimeFaces 3.5
I need when clicking on p:commandButton to check the validation first of all (input text required=true)
if validationFail == false then
Call the popup dialog from js :
else
show requiredMessage from inputText (this field is mandatory...)
I have tried with oncomplete but it calls my bean and after the js popup dialog. I dont want it.
I need in this order : click p:button -> check validation -> if not fails -> show primefaces dialog.
if fails after validation-> render message
My xhtml :
<p:commandButton id="btnSalvar"
value="abc"
action="#{notaFiscalManagedBean.salvar}"
oncomplete="if (args.validationFailed) return true; else return showPF_DiagBox()"
in my showPF dialog I call bean method. if OK clicked by user.
It is better to user RequestContext of primefaces which allows user to execute javascript which is set from managed bean. You can use it by modifying your method at #{notaFiscalManagedBean.salvar} as shown below.
public String salvar(){
boolean valid=true;
//Do your validation here
if(valid){
RequestContext.getCurrentInstance().execute("showPF_DiagBox()");
}
}
If you want to do the validation on client side before submitting the request to the server then just do the following change in your code,
<p:commandButton id="btnSalvar"
value="abc"
action="#{notaFiscalManagedBean.salvar}"
onclick="if(validationFailed()){return false}"
oncomplete="showPF_DiagBox()"/>
Also write down a javascript function to do validations
function validationFailed(){
//Check various conditions based on component validations and return whether validatoin failed or not
}
Try this:
<p:commandButton id="btnSalvar"
value="abc"
action="#{notaFiscalManagedBean.salvar}"
update="#form"
render="#form"/>
By adding 'render' and 'update' attributed your form will have to reload, and then process all the validations inside of it's form.
Hope this can help you, good luck!
In my oncomplete commandButton I got what I wanted getting from #BalusC answer (How to find indication of a Validation error (required="true") while doing ajax command) and #Tuukka Mustonen (JSF 2.0 AJAX: Call a bean method from javascript with jsf.ajax.request (or some other way)) and making some adjustments to fit my needs.
This way, if there are any validation errors or any converters do be validated, they are rendered at screen first of all. If there are not validation errors so I execute my js function and inside it I fire my bean method if needed.
thanks for everybody ! :)
I've got a Primefaces command button that I need to add a callback to in jQuery on document.ready. Basically what I've been trying to do is get a reference to the existing function and then call it in a new function that I wrote:
var existingFunction = jQuery("[id~='submit']").live("click");
jQuery("[id~='submit']").live("click", function(){
existingFunction();
alert('test');
updateControlPanel(buildControlPanelUrl(getUrlVars()));
});
It seems simple enough to me but for some reason this will not work. When I load the page and click the submit button it doesn't even reach the alert.
I've checked the error console and found that it's throwing the following errors:
((f.event.special[s.origType] || {}).handle || s.handler).apply is not a function
There is existing jQuery functions on the page that I did not write but I'd like to make sure this error is not related to the way I'm approaching this.
I'm using tomcat 6 with an older version of JQuery (1.3 or 1.4 ).
Thanks and let me know if you guys need any more info.
Edit
I've put up an example of what I'm trying to do on JS Fiddle: http://jsfiddle.net/anSXH/2/
Here is some further clarification:
I've built the button as a project in JSF 2.0 (MyFaces) using the latest Primefaces component library. I've then taken that button and embedded it into an existing web page. The button submits the form and then calls a JavaScript function to show the result on the page after an ajax request is complete. This all works when I embed the button onto the page but I now need to update something on the client side after the button calls the function. That's why I'm looking at adding a callback to the existing onclick function.
As a side note, because I'm using Primefaces I can attach a JavaScript function to run after the ajax request is complete. My plan B is to try and access this function and somehow override it.
Edit part 2
Here is the generated control from primefaces:
<button
id="topsaveform:submittop"
name="topsaveform:submittop"
class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
onclick="PrimeFaces.ab({source:'topsaveform:submittop',process:'topsaveform OEIMeasurementsTable',update:'errorMessages submittedPopup',onstart:function(cfg){jQuery('#loadingBar').show('fast');;},oncomplete:function(xhr,status,args){postSubmit();;}});return false;"
type="submit">
<span class="ui-button-text">Save</span>
</button>
Did you try making the original function die (ref)?
jQuery("[id~='submit']").die("click");
jQuery("[id~='submit']").live("click", function(){
alert('test');
updateControlPanel(buildControlPanelUrl(getUrlVars()));
});
The problem was that I was trying to do this with a primefaces button. When I switched to a standard JSF button I was able to affix the function to it no problem.
I have a very strange issue on Jquery and partial postback on updatepanel.
What I have done is created a jquery logic in code behind and used :
Page.ClientScript.RegisterStartupScript(this.GetType(), "jsSlider" + select.ClientID, sb.ToString());
to create the Jquery Slider feature in a repeater. However Whats happening is when I put this within inside updatepanel it runs ok and the jquery slider works however any partial postback and I lose my lovely jquery slider feature because I need to re-bind the slider feature back after each partial postback.
How can I do this using similar code like Page.ClientScript.RegisterStartupScript(this.GetType(), "jsSlider" + select.ClientID, sb.ToString());
Is there another way to say Page.ClientScript.EVERYPOSTBACK(this.GetType(), "jsSlider" + select.ClientID, sb.ToString()); or something?? I am open to other suggestions?
you can use the "pageLoad" function in your javascript on your front end code. The pageLoad function gets called on the initial pageload and after every partial postback. If there are things that only need to be called on the initial page load, you would still want to put them in document ready.
<script type="text/javascript">
function pageLoad()
{
//...
//anything you want to happen every time the page loads or after a partial postback
//...
//your javascript here... below an example of using jquery on some asp.net control.
$('#<%= select.ClientID %>').foo('bar');
}
</script>
http://www.asp.net/ajax/documentation/live/overview/AJAXClientEvents.aspx has some more details about this about 1/3 of the way down the page.
If you still need the answer, there's an analog of ClientScript.RegisterStartupScript for UpdatePanel's partial postback. Try ScriptManager.RegisterStartupScript instead.