Script.aculo.us with Seam Remoting
d1g Apr 10, 2006 1:30 PM
Hi. I've managed to get the script.aculo.us InPlaceEditor control working with Seam Remoting and I thought I'd share this.
I'm aware that I could have used MyFaces or other tags to achieve a similar AJAX functionality but I was keen to use script.aculo.us directly with Seam Remoting. I know that script.aculo.us is used by some JSF tags - but these are not geared towards Seam Remoting.
I'm using the most recent versions of script.aculo.us and prototype. I'm also using a recent version of Seam from CVS. You'll need to read up on Seam Remoting and script.aculo.us to understand what's below.
My solution involves extending Ajax.InPlaceEditor using the extension technique of script.aculo.us. Here is my extension:
/* * InPlaceEditor extension for Seam Remoting. */ Ajax.InPlaceEditor.prototype.__initialize = Ajax.InPlaceEditor.prototype.initialize; Ajax.InPlaceEditor.prototype.__onSubmit = Ajax.InPlaceEditor.prototype.onSubmit; Ajax.InPlaceEditor.prototype.__onComplete = Ajax.InPlaceEditor.prototype.onComplete; Ajax.InPlaceEditor.prototype = Object.extend(Ajax.InPlaceEditor.prototype, { initialize: function(element, componentName, componentMethodName, componentParams, componentCallback, options) { SeamRemote.log("initialize()\n"); this.__initialize(element, '/seam/remoting' + SeamRemote.PATH_EXECUTE, options); this.setOptions(options); this.componentName = componentName; this.componentMethodName = componentMethodName; this.componentParams = componentParams; this.componentCallback = componentCallback; this.component = SeamRemote.create(this.componentName); }, onSubmit: function() { SeamRemote.log("onSubmit()\n"); SeamRemote.displayLoadingMessage(); this.componentParams.push(this.editField.value); var call = SeamRemote.createCall(this.component, this.componentMethodName, this.componentParams, this.componentCallback); SeamRemote.pendingCalls.put(call.id, call); var envelope = SeamRemote.createEnvelope(SeamRemote.createHeader(), call.data); var ajaxOptions = { method: 'post', postBody: envelope } this.options.ajaxOptions = ajaxOptions; // this.options.ajaxOptions = Object.extend(this.options.ajaxOptions, ajaxOptions); return this.__onSubmit(); }, onComplete: function(transport, element) { SeamRemote.log("onComplete() " + this.element + "\n"); Element.removeClassName(this.form, this.options.loadingClassName); SeamRemote.requestCallback(transport, SeamRemote.processResponse); }, setOptions: function(options) { this.options = Object.extend(Object.extend(this.options, { evalScripts: true }), options || {}); } });
I'm sure there is a better way of coding much of this and I'm not sure I've done this 100% correctly. You can see that I've borrowed code from both Seam Remoting and script.aculo.us to get this working.
In the header of my template.xhtml I have:
<script src="/js/prototype.js" type="text/javascript"></script> <script src="/js/scriptaculous.js" type="text/javascript"></script> <script src="/seam/remoting/resource/remote.js" type="text/javascript"></script> <script src="/seam/remoting/interface.js?optionsBean&updaterBean" type="text/javascript"></script> <script type="text/javascript"> //<![CDATA[ SeamRemote.getContext().setConversationId('${conversation.id}'); // ]]> </script>
I have two Seam components registered here and I am setting the conversation id. Here is how I'm using the control:
<t:dataList id="aList" value="#{myCollection}" var="item" rowIndexVar="rowIndex" layout="unorderedList"> <span id="item${rowIndex}">${item.name}</span> <script type="text/javascript"> //<![CDATA[ new Ajax.InPlaceEditor( 'item${rowIndex}', 'updaterBean', 'updateName', new Array('${item.id}'), function(result) { element = document.getElementById("item${rowIndex}"); element.innerHTML = result; new Effect.Highlight(element, {startcolor: this.options.highlightcolor}); }); // ]]> </script> </t:dataList>
This iterates over a collection of objects that have a 'name' property. The user can edit the name and the value is updated on the server via Seam Remoting.
That's it! My application has Web 2.0 looking field editing backed up by EJB3 Seam components.
I'll document this on the Wiki if there is interest. I also intend to have a go at making some of the other script.aculo.us AJAX controls work with Seam too.
I'd be interested to hear what people think of this solution - in particular how it relates to Seam Remoting.