« Modifying Dojo to use Domino's OutputFormat=JSON | Main| FilteringSelect and Dialog Lists and Firefox »

xhrPost to Domino

Category   
Bookmark : del.icio.us  Technorati  Digg This  Add To Furl  Add To YahooMyWeb  Add To Reddit  Add To NewsVine 


Hi, David Bockes here.  I've been working on a pretty extensive Dojo & Domino application.  I have quite a few things that I should be blogging that have come out of this project that may be of interest, however I have been lax to do so.  But, I'm going to try and correct that now.  So, let's start with an issue that came up when trying to post a form back to the Domino server using xhrPost to save through Ajax.

I noticed that I would get inconsistant save results and that sometimes all the data in the form would save correctly and sometimes it would cutoff the data at a certain point.  I then found that this would be based on whether or not data had been entered into fields that had been set as widgets (in this case the DateTextBox widget).  The field had been defined as a widget by adding the following to the html attributes:

dojoType="dijit.form.DateTextBox" constraints="{datePattern: 'dd-MM-yyyy'}" required="true" promptMessage="dd/mm/yyyy" invalidMessage="Invalid date.  Use dd/mm/yyyy format."

When sent to the browser, the outputted html for this field looks like this:

input name="ir_lh_Incident_Date" value="" dojoType="dijit.form.DateTextBox" constraints="{datePattern: 'dd-MM-yyyy'}" required="true" promptMessage="dd/mm/yyyy" invalidMessage="Invalid date.  Use dd/mm/yyyy format." id="ir_lh_Incident_Date"

Note that in addition to a name, I also made sure to add an id in the properties box for this field (a good best practice for your Dojo stuff).  Now, when this is parsed by dojo, the resulting html looks like this:

input id="ir_lh_Incident_Date" class="" type="text" autocomplete="off" dojoattachevent="onfocus,onblur:_onMouse,onkeyup,onkeypress:_onKeyPress" dojoattachpoint="textbox,focusNode" tabindex="0" value="" aaa:valuenow="" aaa:invalid="true" aaa:disabled="false" style=""

input type="text" value="" style="display: none;" name="ir_lh_Incident_Date"

Notice that two fields are created, one only has an id and no name and is the displayed version of the field that will show the date picker when clicked on.  Right beneath that is a hidden version of the field that has a name but no id.  When this form is submitted, the value from the display field is placed in the hidden field and is what gets saved into our document.  However, the problem with the data save problems is due to the display version of the field.  Domino is looking to match up the fields based on the name, not the id.  The display version has no name, just an id.  Now, you'd think that this would just get ignored, but it didn't.

I attempted to correct the issue in a WebQuerySave agent both by trying to strip out the no name fields or to only get the named fields and copy those.  However this, since it's kinda a buggy problem, didn't work.  So instead we took the approach of preventing the no name fields from being submitted in the first place.  This was done by editing the Dojo source code and recompiling the custom Dojo build that I'm using.

To fix this, we have to use a "source" version of Dojo.  A source version has the code that makes up the dojo.js and dijit.js split out into individual js files.  In this case, we needed to edit the dojo\_base\xhr.js file.  In there is a function called "formToObject" that is called as part of the xhrPost process.  This function uses a dojo query to get only form elements on the page to submit to the server, leaving behind everything else.  The key line for us is:

var iq = "input:not([type=file]) :not([type=submit]) :not([type=image]) :not([type=reset]) :not([type=button]), select, textarea";

This line builds the query to be used.  Notice that it contains inclusions and exclusions (i.e., :not).  The fix was to change the line to:

var iq = "input:not([type=file]) :not([type=submit]) :not([type=image]) :not([type=reset]) :not([type=button])
[name], select, textarea";

Notice the inclusion of "[name]".  This tells the query that the required item has to have a name attribute, if not, it is to be excluded.  After making this change and recompiling the custom build, the problem was resolved.  The no name fields were no longer submitted and all of the submitted data made it into the document in the back end.  This resolution needs to be used in both Dojo 0.9 and 1.0.  This was found to be a problem on R6 & R7 servers (I haven't tested on R8).

Comments

Gravatar Image1 - Emoticon

Gravatar Image2 - Posting fixed.

Thanks for submitting this David. You and I have a lot to catch up on here.

Gravatar Image3 - Another way

You can also prevent the 'nameless' INPUTs from being sent by using dojo.query():


dojo.query( "INPUT", frm ).filter(
function(inputnode) {
return (inputnode.name == '');
}
).orphan();



This removes all INPUT nodes with no name. Then submit the form normally using dojo.xhrPost().


Gravatar Image4 - I've only tried it against Domino, so can't speak for other app servers. Though I don't think it would hurt to change the rule. I can't think of a case where you'd want unnamed fields, but just because I can't think of one doesn't mean there isn't a valid reason for it. An alternate solution may be to make it a parameter of the post that lets you decide if you'd like it to exclude those or not.

Gravatar Image5 - @6:

The Dojo XHRPost (version 1.0 at least) accepts also form nodes. I am using this in my application:

var kw = { url: frm.action,
load: function (data) {
targetPane.setContent(data);
},
error: function(data) {
console.log('error: '+data);
targetPane.setContent(data);
},
timeout: 3500,
form: frm
};

dojo.xhrPost(kw);


The 'frm' that above code is referencing gets created as pass-thru HTML with Computed Text on a Domino form:

var frm = document.forms['<Computed Text>']

and value for the text is:

"_" + Form

Gravatar Image6 - Ah, my apologies. Yes, that makes sense! That sounds like an elegant solution indeed. Sorry I misunderstood you the first time. Sounds like David got it right away Emoticon He always was the smarter one in the family.

Thanks for sharing.

Gravatar Image7 - Emoticon

Gravatar Image8 - If I'm reading this correctly, it won't work because the dojo.query is only going to return a set of filtered nodes.

xhrPost will take the form name as its argument and then post all the fields it finds in that form, thus ignoring the query result just performed.

If, on the other hand, you are saying use dojo.query to get the nodes, perform your own node destruction, and then do xhrPost, yes, I assume that would work.

However, the problem should be fixed in the dojo source regardless. There's no value in submitting name/value pairs in a post to the backend if you don't have a name
Emoticon

Gravatar Image9 - So, just to clarify, is this Domino-specific? Or do you feel we should we change the match rule generally?

Gravatar Image10 - Domino may have more rigorous (read as less flexible perhaps) handling of the post data that causes it to error out. So perhaps other web servers are able to better handle this condition.

But I agree with David in that I can't really see a use-case where a submission of data without a name pair provides any value. For example, what would you do with this data stream resulting from a post:

firstName=Lance&lastName=Spellman&=888-111-1111&=Phoenix&State=AZ

You and I know by looking at it that the 888-111-1111 is a phone number, but the web server won't. And even if it could distinguish that, is it the office, home, or cell number? So the data has no value, and the potential for causing error on the server.

Also, since the data that will be submitted this way is NOT the core form data anyway, but simply the dojo mechanics for building widgets on the screen, it's unnecessary data.

For all those reasons, I would make the filter universal in the Dojo source. We'd submitted a bug in Tracker with the fix, but I can't locate it now.

Gravatar Image11 - Hmm... it seems I was not clear enough. I understood that you said that:


"it won't work because the dojo.query is only going to return a set of filtered nodes. xhrPost will take the form name as its argument"


My point was that xhrPost also accepts the form itself as parameter. Thus in my example above, when i write:

var kw = {

(...other stuff...)

form: frm
};

this frm is the DOM node that was modified with dojo.query and thus has the 'nameless' values removed.

So, I do not pass the form name to xhrPost. I pass the modified form itself. I included the rest of the code so that you could see where the frm was coming from.

Hope I was more clear this time.

This code actually works in my application (I am using dojo 1.0.0 from AOL CDN). I understand that change to source is not big, however I would not like to maintain a locally patched version.

Generally I agree with you that nameless values should not be sent to server. Maybe this will be fixed in 1.0.2.

Gravatar Image12 - I understand, but that's a different issue. That's dealing with the idea of Domino's handling/mangling of form names as it spits out the HTML to the browser.

The issue we're dealing with here is that once the form is rendered, along with all the little dojo widget bits and insertions, the input fields that are now inside that form don't all have 'name' attributes. When you use xhrPost, you are giving it the form element and it will scrape all the input tags inside that form to submit to the server.

Where it breaks is when those input fields don't have a name (what dojo does with some of it's helper input fields).

We don't really need to make a big deal of this, I'm sure it will be fixed in a maintenance release, and if you're in a hurry, it's 5 characters on one line of code in the dojo source to fix it.

Gravatar Image13 - Excellent, thanks for passing that info along. I like you solution and will give it a try. Obviously if I can make that work without needing to modify source, that is the optimal situation.

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)