What I'm trying to do is zoom to the selected feature and then send the map to the printer. Then zoom to the buffer and again print the resulting map to the printer. Each of the following steps works by themselves. However, I'm having a problem figuring out how to sequence the statements and use timeouts to ensure that each step is completed before the next process starts? Here's my code:
//Zoom to Parcel
setTimeout(lang.hitch(this, function () {
this.zoomselected();
}), 3000);
setTimeout(lang.hitch(this, function () {
html.setStyle(this.PrintMessage, 'display', 'block');
}), 5000);
//Zoom to Buffer
setTimeout(lang.hitch(this, function () {
this.zoombuffer();
}), 3000);
setTimeout(lang.hitch(this, function () {
html.setStyle(this.PrintMessage, 'display', 'block');
this.sendToPrinter_SoilErosion(sTitle,sLayout,sFormat,sMessage);
}), 5000);
Hey Tom,
I would suggest its better to use dojo Deffered to chain these functions rather than using timeouts.
Getting Started with Deferreds - Archived Tutorial - Dojo Toolkit
- Girish
Dojo makes it easy:
Deferred and Promise chaining tests - JSFiddle
Here's another example for chaining using Mootools:
Chaining Javascript functions with callbacks - JSFiddle
And jQuery:
http://stackoverflow.com/questions/5230333/how-to-avoid-callback-chains
Note, the jsfiddles aren't mine! Additionally, regarding jQuery, here's some info on queue vs deferred objects:
Girish,
Thanks for your quick reply. That makes a lot of sense. I'll let you know how it goes.
Tom
Girish and Chris,
I reviewed the samples using dojo deferred, but I'm still not sure how to make this work. I'm not very experienced in dojo, so I'm looking for a simple example using the ArcGIS JavaScript api.
I'm trying to execute the following two functions which work fine if I stop each of them using alert.
this.zoomselected();
this.sendToPrinter_SoilErosion(sTitle,sLayout,sFormat);
I tried all kinds of deferred statements like the following, but nothing seems to work.
var def = new Deferred();
def = this.zoomselected();
def.then(function() {
this.sendToPrinter_SoilErosion(sTitle,sLayout,sFormat);
});
Does anyone have any similar examples I can look at?
Thanks.
Tom
Hey Tom,
Yeah, initially its a bit tricky to understand deferred and promise but once you get your hands dirty its very simple and cool. Most of the ESRI javascript API functions already return deferred where ever necessary. So its even easier to use it for ESRI javascript API. Here is an example to chain ajax calls using dojo deferred and promise. Dojo Deferred - Chaining - JSFiddle .
Its a very simple functionality to print map in two different scales.
here is a crux of it:
function printMap(){ var printTask = new PrintTask("http://sampleserver6.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%2..."); var printTemplate = new PrintTemplate(); printTemplate.layout = "MAP_ONLY"; //"A4 Portrait"; printTemplate.preserveScale = false; var params = new PrintParameters(); params.map = this.map; params.template = printTemplate; dom.byId("printButtonNode").innerHTML = "Printing..."; return printTask.execute(params); }; function zoomToSelectedFeatures(){ var selectedExt = map.extent; return map.setExtent(selectedExt); }; function zoomToBufferedFeatures(){ var bufferedExt = map.extent.expand(1.5); return map.setExtent(bufferedExt); }; function addResults(results){ var resultContainer = dom.byId("results"); domConstruct.place('<div><a href="' + results.url + '" target="_blank">Map </a></div>', resultContainer); dom.byId("printButtonNode").innerHTML = "Print"; }; on(dom.byId("printButtonNode"), "click", function(){ dom.byId("results").innerHTML = ""; zoomToSelectedFeatures() .then(printMap) .then(addResults) .then(zoomToBufferedFeatures) .then(printMap) .then(addResults); }); });
Thanks
-Girish
Girish,
That was super helpful and I think I'm getting close. However, when I run zoombuffer first, it zooms to the buffer but when it tries to run the zoomselected function, it thinks that this.selValueShapeFeatures is undefined. When I reverse the order, then zoomselected zooms to the selected feature, but when it tries to run the zoombuffer, it thinks that this.graphicsLayerBuffer is undefined. What am I missing? Here's the simple code:
onTest: function () {
this.zoombuffer()
.then(this.zoomselected)
.then(this.zoombuffer);
},
zoomselected: function () {
if (this.selValueShapeFeatures) {
var features = this.selValueShapeFeatures;
if (features.length != 0) {
var graphics = features;
var gExt = graphicsUtils.graphicsExtent(graphics);
var selectedExt = gExt.expand(1.1);
return this.map.setExtent(gExt.expand(1.1));
} else {
return null;
}
}
},
zoombuffer: function () {
if (this.graphicsLayerBuffer) {
if (this.graphicsLayerBuffer.graphics.length > 0) {
var graphics = this.graphicsLayerBuffer.graphics;
var gExt = graphicsUtils.graphicsExtent(graphics);
var bufferExt = gExt.expand(1.1);
return this.map.setExtent(bufferExt);
}
} else {
return null;
}
},
Thanks.
Tom
You need to lang.hitch the calls to these functions to set the execution scope.
add "dojo/_base/lang" to the imports and
onTest: function () {
this.zoombuffer()
.then(lang.hitch(this, this.zoomselected))
.then(lang.hitch(this, this.zoombuffer));
},
-Girish
Girish,
OK almost there. Nothing is erroring out, but I've got a couple odd things that happen. On the positive, all of the functions get executed and 2 reports get printed entitled "Title 1" and Title 2" as specified. On the negative, the map extent in the printout remains unchanged. It is not affected by zoomselected or zoombuffer. It doesn't seem like the map completely refreshes itself before it creates the print task. Any thoughts? Here's my code.
this.zoomselected() | ||
.then(lang.hitch(this, this.sendToPrinter_SoilErosion("Title 1",sLayout,sFormat,sMessage))) | ||
.then(lang.hitch(this, this.zoombuffer)) | ||
.then(lang.hitch(this, this.sendToPrinter_SoilErosion("Title 2",sLayout,sFormat,sMessage))); |
Thanks for your help!
Tom
I tried to follow Girish's example and I kept the code example as simple as possible (See below). However, the map extent in the print layout doesn't get affected by the zoombuffer function. I've tried everything, but I can't get it to work. I must be missing something!!
onTest: function () { |
//This executes both but doesn't zoom to the same extent | |
this.zoombufferTest() | |
.then(lang.hitch(this, this.sendToPrinter_Test())); | |
}, | |
zoombufferTest: function () { |
var bufferExt = this.map.extent.expand(4.0); | |
return this.map.setExtent(bufferExt); | |
}, | |
sendToPrinter_Test: function () { | |
var sTitle = "Test"; | |
var sLayout = "WRC_Landscape"; | |
var sFormat = "PDF"; | |
//Get the user settings from the form | |
this.printTask = new PrintTask(this.printTaskURL, this.printParams); | |
var template = new PrintTemplate(); | |
template.label = sTitle; | |
template.layout = sLayout; | |
template.format = sFormat; | |
template.preserveScale = false; | |
this.printParams.map = this.map; | |
this.printParams.template = template; | |
return this.printTask.execute(this.printParams, this.printComplete, this.printError); | |
}, Map before running code: Print layout (note zoom not reflected): Map after running code (zoomed out 4x) |