How to printout the current map view?

1532
23
03-01-2019 12:48 PM
CarlTownsend1
New Contributor III

I'm trying to add a map printout functionality to my javascript 3.27 based map, and I've got a problem with the print functions. In the print script code there is this:

......
        Printapp.map = new esri.Map
  ("map",
  {
          basemap: "topo",
         center: [-102, 54.75],
          zoom: 6,
         slider: false
       }
 );

.........
But I already have other script basically to loop through a map service and show the layers with the map type, coordinates and layers on startup. Then I click print, it defaults to this instead of what's on the screen. I can change the zoom level, basemap map type etc. and it will print out the changes instead of what's showing on the screen.

If I comment this bit out, it doesn't work. Basically I just want the print function to print out what's on the current map screen. How do I do this?

Thanks

0 Kudos
23 Replies
CarlTownsend1
New Contributor III

Hi Robert, yep, I agree, this should be simple...Anyway, This is the code to dynamically load the map layers by looping through the map service:

<script src="https://js.arcgis.com/3.27/"></script>
<script> 
//Dynamic layer script. Loops through a map service for all layers and automatically lists them in a map.
      var layer, map, mapLegend, visible = [];
      require([
        "esri/map",
        "esri/layers/ArcGISDynamicMapServiceLayer",
        "dojo/dom", 
        "dojo/on",
        "dojo/query",
        "dojo/_base/array",
        "dojo/domReady!"        
      ], function(
        Map, ArcGISDynamicMapServiceLayer,
        dom, on, query, arrayUtils
      ) {
  
        map = new Map(
  "map",
  {basemap: "satellite",
  center: [-102, 54.75],
  slider: true,
  nav: false,
  zoom: 6});


//Point the url below to the published mapservice you want to use    
        layer = new ArcGISDynamicMapServiceLayer("https://xxxxxxx/arcgis/rest/services/Test/DMAF_Application_V3/MapServer",{
    "showAttribution": true, "opacity": 0.7, mode: ArcGISDynamicMapServiceLayer.MODE_ONDEMAND,
            outFields: ["*"],
            });
       
        layer.on("load", buildLayerList);
        map.addLayer(layer);

        function buildLayerList() {
          var items = arrayUtils.map(layer.layerInfos, function(info, index) {
            if (info.defaultVisibility) {
              visible.push(info.id);
            }
            return "<input type='checkbox' class='list_item'" + (info.defaultVisibility ? "checked=checked" : "") + "' id='" + info.id + "'' /><label for='" + info.id + "'>" + info.name + "</label>";
          });
          var ll = dom.byId("layer_list");
          ll.innerHTML = items.join(' ');
          layer.setVisibleLayers(visible);
          on(ll, "click", updateLayerVisibility);
        }

        function updateLayerVisibility() {
          var inputs = query(".list_item");
          var input;
          visible = [];

          arrayUtils.forEach(inputs, function(input) {
            if (input.checked) {
              visible.push(input.id);
            }
          });
//if there aren't any layers visible set the array to be -1
          if (visible.length === 0) {
            visible.push(-1);
          }
          layer.setVisibleLayers(visible);
        }  
      });
  
</script>

And this is the print code:

script src="https://js.arcgis.com/3.27/"></script>
<script>
//Print a map script
      var Printapp = {};
      require([
        "esri/map",
  "esri/layers/FeatureLayer",
        "esri/dijit/Print",
  "esri/tasks/PrintTemplate",
        "esri/request",
  "esri/config",
        "dojo/_base/array",
  "dojo/dom",
  "dojo/parser",
        "dijit/layout/BorderContainer",
  "dijit/layout/ContentPane",
  "dojo/domReady!"
      ], function(
        Map, FeatureLayer,
        Print, PrintTemplate,
        esriRequest, esriConfig,
        arrayUtils, dom, parser
      ) {
        parser.parse();

   Printapp.printUrl =  "https://xxxxxxxxxxxx/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task";

        esriConfig.defaults.io.proxyUrl = "/proxy/";
  
  Printapp.map = new Map("map",
  {
  basemap: "topo",
  center: [-102, 54.75],
  slider: true,
  nav: false,
  zoom: 6});

// add graphics for layers
        var layerUrl = "https://xxxxxxxxxxx/arcgis/rest/services/Test/DMAF_Application_V3/MapServer"; 
        var printFeatureLayer = new FeatureLayer(layerUrl, {
          "mode": FeatureLayer.MODE_SNAPSHOT
        });  
        Printapp.map.addLayer(printFeatureLayer);

// get print templates from the export web map task
        var printInfo = esriRequest({
          "url": Printapp.printUrl,
          "content": { "f": "json" }
        });
        printInfo.then(handlePrintInfo, handleError);

        function handlePrintInfo(resp) {
          var layoutTemplate, templateNames, mapOnlyIndex, templates;

          layoutTemplate = arrayUtils.filter(resp.parameters, function(param, idx) {
            return param.name === "Layout_Template";
          });
         
          if ( layoutTemplate.length === 0 ) {
            console.log("print service parameters name for templates must be \"Layout_Template\"");
            return;
          }
          templateNames = layoutTemplate[0].choiceList;

// remove the MAP_ONLY template then add it to the end of the list of templates
          mapOnlyIndex = arrayUtils.indexOf(templateNames, "MAP_ONLY");
          if ( mapOnlyIndex > -1 ) {
            var mapOnly = templateNames.splice(mapOnlyIndex, mapOnlyIndex + 1)[0];
            templateNames.push(mapOnly);
          }
        
// create a print template for each choice
          templates = arrayUtils.map(templateNames, function(ch) {
            var plate = new PrintTemplate();
            plate.layout = plate.label = ch;
            plate.format = "PDF";
            plate.layoutOptions = {
              "authorText": "Made by: xxxxxxxxx",
              "copyrightText": "<copyright info here>",
              "legendLayers": [],
              "titleText": "Title",
              "scalebarUnit": "Miles"
            };
            return plate;
          });


          // create the print dijit
          Printapp.printer = new Print({
            "map": Printapp.map,
            "templates": templates,
            url: Printapp.printUrl
          }, dom.byId("print_button"));
          Printapp.printer.startup();
        }
        function handleError(err) {
          console.log("Something broke: ", err);
        }
      });
  
</script>

In the page, the print script is directly under the dynamic map script code, which runs first. The trouble is, in this section in the print script:
Printapp.map = new Map("map",
  {
  basemap: "topo",
  center: [-102, 54.75],
  slider: false,
  nav: false,
  zoom: 6});

it is insisting I have a new map. If I change it or do anything to this the code doesn't work. I have been trying many things, too many to go into details here, but usually the print button disappears or when I click it, nothing happens. Sometimes the generate legend script stops working too. I just want this print code to printout what is showing in the current map view. I have a resizable div section at the bottom of the mapping screen which I'm going to use in future for attribute tables, and when I drag resize it up and down, I can see the topo basemap drawing underneath, which I don't want.

Thanks!

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Carl,

   So if you are going to use multiple JS files then like I said in a previous reply you can either use a window global variable for the map object or pass the map object directly to your print code when you call the print code:

<script src="https://js.arcgis.com/3.27/"></script>
<script>
  //Dynamic layer script. Loops through a map service for all layers and automatically lists them in a map.
  var layer, map, mapLegend, visible = [];
  require([
    "esri/map",
    "esri/layers/ArcGISDynamicMapServiceLayer",
    "dojo/dom",
    "dojo/on",
    "dojo/query",
    "dojo/_base/array",
    "dojo/domReady!"
  ], function(
    Map, ArcGISDynamicMapServiceLayer,
    dom, on, query, arrayUtils
  ) {

    window.map = new Map(
      "map", {
        basemap: "satellite",
        center: [-102, 54.75],
        slider: true,
        nav: false,
        zoom: 6
      });


    //Point the url below to the published mapservice you want to use     
    layer = new ArcGISDynamicMapServiceLayer("https://xxxxxxx/arcgis/rest/services/Test/DMAF_Application_V3/MapServer", {
      "showAttribution": true,
      "opacity": 0.7,
      mode: ArcGISDynamicMapServiceLayer.MODE_ONDEMAND,
      outFields: ["*"],
    });

    layer.on("load", buildLayerList);
    window.map.addLayer(layer);

    function buildLayerList() {
      var items = arrayUtils.map(layer.layerInfos, function(info, index) {
        if (info.defaultVisibility) {
          visible.push(info.id);
        }
        return "<input type='checkbox' class='list_item'" + (info.defaultVisibility ? "checked=checked" : "") + "' id='" + info.id + "'' /><label for='" + info.id + "'>" + info.name + "</label>";
      });
      var ll = dom.byId("layer_list");
      ll.innerHTML = items.join(' ');
      layer.setVisibleLayers(visible);
      on(ll, "click", updateLayerVisibility);
    }

    function updateLayerVisibility() {
      var inputs = query(".list_item");
      var input;
      visible = [];

      arrayUtils.forEach(inputs, function(input) {
        if (input.checked) {
          visible.push(input.id);
        }
      });
      //if there aren't any layers visible set the array to be -1
      if (visible.length === 0) {
        visible.push(-1);
      }
      layer.setVisibleLayers(visible);
    }
  });
</script>

<script src="https://js.arcgis.com/3.27/"></script>
<script>
  //Print a map script
  var Printapp = {};
  require([
    "esri/layers/FeatureLayer",
    "esri/dijit/Print",
    "esri/tasks/PrintTemplate",
    "esri/request",
    "esri/config",
    "dojo/_base/array",
    "dojo/dom",
    "dojo/parser",
    "dijit/layout/BorderContainer",
    "dijit/layout/ContentPane",
    "dojo/domReady!"
  ], function(
    FeatureLayer,
    Print, PrintTemplate,
    esriRequest, esriConfig,
    arrayUtils, dom, parser
  ) {
    parser.parse();

    Printapp.printUrl = "https://xxxxxxxxxxxx/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task";

    esriConfig.defaults.io.proxyUrl = "/proxy/";

    Printapp.map = window.map

    // add graphics for layers
    var layerUrl = "https://xxxxxxxxxxx/arcgis/rest/services/Test/DMAF_Application_V3/MapServer";
    var printFeatureLayer = new FeatureLayer(layerUrl, {
      "mode": FeatureLayer.MODE_SNAPSHOT
    });
    Printapp.map.addLayer(printFeatureLayer);

    // get print templates from the export web map task
    var printInfo = esriRequest({
      "url": Printapp.printUrl,
      "content": {
        "f": "json"
      }
    });
    printInfo.then(handlePrintInfo, handleError);

    function handlePrintInfo(resp) {
      var layoutTemplate, templateNames, mapOnlyIndex, templates;

      layoutTemplate = arrayUtils.filter(resp.parameters, function(param, idx) {
        return param.name === "Layout_Template";
      });

      if (layoutTemplate.length === 0) {
        console.log("print service parameters name for templates must be \"Layout_Template\"");
        return;
      }
      templateNames = layoutTemplate[0].choiceList;

      // remove the MAP_ONLY template then add it to the end of the list of templates 
      mapOnlyIndex = arrayUtils.indexOf(templateNames, "MAP_ONLY");
      if (mapOnlyIndex > -1) {
        var mapOnly = templateNames.splice(mapOnlyIndex, mapOnlyIndex + 1)[0];
        templateNames.push(mapOnly);
      }

      // create a print template for each choice
      templates = arrayUtils.map(templateNames, function(ch) {
        var plate = new PrintTemplate();
        plate.layout = plate.label = ch;
        plate.format = "PDF";
        plate.layoutOptions = {
          "authorText": "Made by: xxxxxxxxx",
          "copyrightText": "<copyright info here>",
          "legendLayers": [],
          "titleText": "Title",
          "scalebarUnit": "Miles"
        };
        return plate;
      });


      // create the print dijit
      Printapp.printer = new Print({
        "map": Printapp.map,
        "templates": templates,
        url: Printapp.printUrl
      }, dom.byId("print_button"));
      Printapp.printer.startup();
    }

    function handleError(err) {
      console.log("Something broke: ", err);
    }
  });
</script>
CarlTownsend1
New Contributor III

Are there any examples of how this is done? Seeing some code makes a lot more sense to me than describing what needs to happen - as I said earlier, I'm not a programmer. I have tried calling the map object to the print script but it hasn't worked.

0 Kudos
CarlTownsend1
New Contributor III

Nevermind. I think I've found some examples. I'll see if I can get this to work.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

??? I provided your code fixed for this in my last reply...

0 Kudos
CarlTownsend1
New Contributor III

Oh yes I see the changes! Sorry, I thought you'd just posted my code back as a quote. It's been a long day. Doh.... Well what you've posted still doesn't work. it says printing when I click on the print button, but it seems to fail silently, with the button going back to Print and no output - similar to what I've been trying. I've even created a new html document with just these two scripts, just in case something was interfering, but nope it still won't print. I've been scouring through the code line by line and I just can't see what's going wrong here 

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Carl,

  So when in the print js file have you console.log ed the map to see if it is a map object?

0 Kudos
CarlTownsend1
New Contributor III

There is no console log that I can see (I wouldn't know where that would be). I'm writing it in notepad++ and it's not a js file, the scripts all in a single html document (for now).

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Carl,

  OK. That makes even less sense then. If all your code is in the same html then why do you have the code in seperate script tags?...

0 Kudos
CarlTownsend1
New Contributor III

I plan on moving them to separate .js files soon. Right now I find that  makes it easy to read and see where one script starts and another finishes, and also I'm not fishing in and out of separate .js files all the time. Makes sense. However, this particular problem has been keeping things on hold.

0 Kudos