Reputation: 5512
I'm using Dojo support for Ajax
function handleSubmit(evt, targetUrl, submitForm, updateDiv) {
dojo.stopEvent(evt);
dojo.xhrPost( {
url: targetUrl,
handleAs: "text",
load: function(response){
updateDiv.innerHTML = response;
wireEvents();
return response;
},
form: submitForm,
error: function(response, ioArgs) {
console.error("HTTP status code: ", ioArgs.xhr.status);
return response;
}
});
}
The response from the server contains more data than what I need. I'd like to be able to substitute this
load: function(response){
updateDiv.innerHTML = response;
wireEvents();
return response;
},
into something like
load: function(response){
updateDiv.innerHTML = dojo.byId('elemToExtract', response);
wireEvents();
return response;
},
I've to update my page with a portion of the ajax response. I need the ability to use the dojo.byId selector over the response (using the response as a context root or something like I found in jQuery).
Do you know how can I achieve this?
Thank you
Upvotes: 2
Views: 5051
Reputation: 5512
Max & seth.. thanks a lot!
At the end the solution is based on what Massimiliano suggested.
I adapted it to dojo 1.2.3 (as this vers. is missing the dojo.empty() function as well). "results[0].innerHTML" needs to be called to extract the dom from the dojo variable. Then, without calling empty(), I can replace directly the innerHTML of the target "updateDiv"
The key point here is the ability of dojo.query() to query a tree passing a domNode as a context (sorry...I'm new to dojo).
load: function(response){
var tempDiv = document.createElement("div");
tempDiv.innerHTML = response;
var results = dojo.query("[id=elemToExtract]", tempDiv);
updateDiv.innerHTML = results[0].innerHTML;
wireEvents();
return response;
},
I'm not sure why but the check "if (results.length) {" is giving problems on runtime. If I debug the JS I think I'm adding some delay and it works ok. The problem is on runtime, it seems that the condition is evaluated to false...I'm not sure why
Thank you again
Upvotes: 0
Reputation: 853
The response you receive is pure text, as defined by the handleAs parameter of the ajax call. If you want to query the markup contained in this response with dojo.byId, you need to convert it into parsed HTML, creating a DOM for it. To do this, you can create a temporary html element with the response; then you can extract the part you need using dojo.byId.
load: function(response){
var tempDiv = dojo.create('div', {innerHTML: response});
updateDiv.innerHTML = dojo.byId('elemToExtract', tempDiv);
wireEvents();
return response;
},
EDIT:
The above contains errors, as dojo.byId requires a Document as second argument, and it does not accept a Node (see also Seth's answer); moreover, it returns a Node instance which cannot be assigned to innerHTML. Ina working solution, when you have the temporary element you need to extract the part you need using dojo.query. Then you can paste it inside the DOM of the real page using dojo.place. Notice that if you want to replace the previous content, you need to delete all the children of the target node with dojo.empty before using dojo.place.
load: function(response){
var tempDiv = dojo.create('div', {innerHTML: response});
var results = dojo.query('[id=elemToExtract]', tempDiv);
if (results.length) {
dojo.empty(updateDiv);
dojo.place(results[0], updateDiv);
wireEvents();
}
return response;
},
Notice that the dojo.place and dojo.create functions was added in versions 1.2 and 1.3 respectively; if you have a previous version, it can be replaced using the DOM api:
load: function(response){
var tempDiv = document.createElement('div');
tempDiv.innerHTML = response;
var results = dojo.query('[id=elemToExtract]', tempDiv);
if (results.length) {
dojo.empty(updateDiv);
updateDiv.appendChild(result[0]);
wireEvents();
}
return response;
},
Upvotes: 4
Reputation: 37267
The problem with this is that dojo.byId
expects a document for the second argument. Another problem is that the ID is not 'known' until the element is placed in the DOM. (I may be wrong on this last point and/or it may depend on browsers. In experiments I performed, dojo.byId didn't return anything until the HTML was in the DOM.)
That being said, you could accomplish what you want by placing the data returned by your ajax call in a hidden element and then using dojo.query
on it.
Assuming you have this in your HTML:
Then your xhrGet looks like this:
dojo.xhrGet( {
url: 'http://jsbin.com/erawu',
handleAs: 'text',
load: function(data) {
var storage = dojo.byId('storage');
storage.innerHTML = data;
var want = dojo.query('#iwant', storage )[0]; // or dojo.query(...).forEach(...)
if (want) {
dojo.byId('hello').innerHTML = want.innerHTML;
// depending on what you want
// you could also use dojo.place( want, dojo.byId('hello'), 'first')
}
},
error: function() {
console.log( arguments );
console.error('ONOES!');
}
});
Here's a working example using dojo 1.2.
Upvotes: 1