XPages: Optimized partial refreshes for event handlers
September 20th, 2014Sven Hasselbach has created an optimized version of the XSP.partialRefreshPost() method. This works great to reduce the number of form fields that are included in the request for a partialRefreshPost.
But his version does not include support for running server-side actions because the the form fields included in the POST doesn't include the server-side event handler.
So I have created an optimized version of his optimized version that supports this 🙂
My versions adds a 'submitid' parameter that should point to the id of the event handler that you want to execute on the server.
XSP.partialRefreshPost( '#{id:somePart}', { clearForm: true, submitid: '#{id:submitEventHandler}' } );
Here's an example of using the optimized partial refresh for an eventhandler:
<xp:button id="button1"> <xp:eventHandler event="onclick" submit="false" id="submitEventHandler" refreshMode="partial" refreshId="somePart"> <xp:this.action><![CDATA[#{javascript:someServerSideAction();}]]></xp:this.action> <xp:this.script><![CDATA[ XSP.partialRefreshPost( '#{id:somePart}', { clearForm: true, submitid: '#{id:submitEventHandler}' } ); ]]></xp:this.script> </xp:eventHandler> </xp:button>
Here's the complete code snippet (available as an OpenNTF XSnippets too):
<xp:scriptBlock id="scriptBlockPROptimized"> <xp:this.value><![CDATA[ XSP.addOnLoad(function(){ // hijack the existing partial refresh method if( !XSP.__partialRefresh ){ XSP.__partialRefresh = XSP._partialRefresh; } // add the new one to the XSP object XSP._partialRefresh = function x_prfh(method, form, refreshId, options){ // clear the form? if( options.clearForm ){ // create a new HTML form... var newForm = document.createElement( "form" ); newForm.setAttribute( "method", form.method ); newForm.setAttribute( "action", form.action ); // ... and loop all existing fields for( var i = 0; i<form.length; i++ ){ var field = form[i]; var fieldName = field.name; var includeField = false; try{ // check for addition fields if( options.additionalFields ){ includeField = dojo.indexOf(options.additionalFields, fieldName)!=(-1)?true:false; } // only add XPages relevant fields and addtional fields if( fieldName == form.id || fieldName.substr(0,2) == '$$' || includeField ){ var newField = null; if( field.options ){ // special handling for fields with options for( var j=0; j<field.length; j++ ){ if( field.options[j].selected ){ newField = document.createElement( "input" ); newField.setAttribute( "type", "hidden" ); newField.setAttribute( "name", fieldName ); newField.setAttribute( "value", field.options[j].value ); newForm.appendChild( newField ); } } }else{ // default field handling: just clone the DOM element // check for $$xspsubmitid option if( options.submitid && fieldName == "$$xspsubmitid"){ newField = document.createElement( "input" ); newField.setAttribute( "type", "hidden" ); newField.setAttribute( "name", "$$xspsubmitid" ); newField.setAttribute( "value", options.submitid ); newForm.appendChild( newField ); } else { newField = field.cloneNode( true ); newForm.appendChild( newField ); } } } }catch(e){ console.log(e); } } // call the original refresh method with the new form return XSP.__partialRefresh(method, newForm, refreshId, options); } XSP.__partialRefresh(method, form, refreshId, options); }; }); ]]></xp:this.value> </xp:scriptBlock>
Keep in mind that to optimize a partial refresh you need to focus on more than just the size of the POST request. You should also look at partial execution mode (execMode="partial") in order to reduce the amount of work that the server has to do.