Custom Text Elements in API 4.13 vs. WAB

357
3
Jump to solution
11-26-2019 05:37 AM
JasonDavenport
New Contributor

I have Custom Text Elements in my print template that works great when using WAB. The Custom fields show up when you click the print widget and gives you a chance to fill them out and it prints out correctly. When I click the print widget using JavaScript 4.13 it doesn't show the text boxes to fill out. Should it? If not, how do I go about making this happen? Is there an an example that I could use? Thanks!

JavaScript snapshot:

WAB snapshot:

Here is my code that I'm using for the print widget:

var print = new Print({
container: document.createElement("div"),
view: view,
printServiceUrl: "https://gisportal.abc.com/server/rest/services/PrintService/GPServer/Export%20Web%20Map",
templateOptions: {
title: "Corporation",
author: "Joe",
format:"pdf",
layout: "1. 8.5x11 Portrait",
copyright: "",
legendEnabled: true,
dpi: 300,
customTextElements: [
{"Text1": ""},
{"Text2": ""},
{"Text3": ""},
{"Text4": ""},
{"Text5": ""},
{"Text6": ""},
{"Text7": ""},
{"Text8": ""}
]
}

})

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Esteemed Contributor

Jason,

   Here is the update to fix those issues. Don't forget to mark this as the correct answer.

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
  <title>Print widget - 4.13</title>
  <link rel="stylesheet" href="https://js.arcgis.com/4.13/esri/themes/light/main.css" />

  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
      overflow: hidden;
    }
  </style>

  <script src="https://js.arcgis.com/4.13/"></script>
  <script>
    var print, templateInfos, layoutOptions;
    require([
      "esri/views/MapView",
      "esri/widgets/Print",
      "esri/WebMap",
      "dojo/aspect",
      "esri/request",
      "dojo/Deferred",
      "dojo/_base/lang",
      "dojo/dom-construct",
      "dojo/query",
      "dojo/_base/array",
      "dojo/on"
    ], function (MapView, Print, WebMap, aspect, esriRequest, Deferred, lang, domConstruct, query, array, on) {
      var webmap = new WebMap({
        portalItem: {
          // autocasts as new PortalItem()
          id: "d6d830a7184f4971b8a2f42cd774d9a7"
        }
      });

      var view = new MapView({
        container: "viewDiv",
        map: webmap
      });

      view.when(function () {
        print = new Print({
          view: view,
          // specify your own print service
          printServiceUrl: "https://gis.calhouncounty.org/arcgis3/rest/services/ExportWebMap/GPServer/Export_Web_Map"
        });

        print.viewModel.watch('state', function (s) {
          if (s === 'ready') {
            setTimeout(function () {
              var layoutTab = query('.esri-print__layout-tab')[0];
              on(layoutTab, 'click', function () {
                _bindEvents();
              });
              _bindEvents();
            }, 200);

            _getLayoutTemplatesInfo().then(function (result) {
              var templatesInfo = result.data;
              if (templatesInfo && !templatesInfo.error) {
                var parameters = templatesInfo && templatesInfo.results;
                if (parameters && parameters.length > 0) {
                  array.some(parameters, lang.hitch(this, function (p) {
                    return p && p.paramName === 'Output_JSON' ?
                      templateInfos = p.value : false;
                  }));
                }
              }
            }).otherwise(function (err) {
              console.info(err);
            });
          }
        });

        // Add widget to the top right corner of the view
        view.ui.add(print, "top-right");

        aspect.around(print.viewModel, "print", function (originalPrint) {
          return function (pt) {
            //get the ce values.
            var ceInputs = query('.esri-print__input-text[data-input-name^=\"ce-\"]');
            var ceArr = [];
            ceInputs.forEach(function (cei) {
              var ceProp = cei.dataset.inputName.replace('ce-', '');
              var ceVal = cei.value;
              var ceObj = {};
              ceObj[ceProp] = ceVal;
              ceArr.push(ceObj);
            });
            pt.layoutOptions.customTextElements = ceArr;
            var deferred = originalPrint(pt);
            return deferred;
          }
        });
      });

      function _addCustomEelements() {
        if (templateInfos) {
          query('.esri-print__input-text[data-input-name^=\"ce-\"]').forEach(function (cei) {
            domConstruct.destroy(cei);
          });
          setTimeout(function () {
            var layout = query('[data-target-property=\"layout\"]')[0];
            var templateInfo = templateInfos[layout.selectedIndex];
            var customTextElements = lang.getObject(
              "layoutOptions.customTextElements",
              false, templateInfo);
            if (customTextElements && customTextElements.length > 0) {
              var textNames = [];
              array.forEach(customTextElements, lang.hitch(this, function (cte) {
                for (var p in cte) {
                  if (textNames.indexOf(p) < 0) {
                    var advCont = query(
                      '.esri-print__advanced-options-container')[0];
                    var copyright = query(
                      '.esri-print__copyright-info-container')[0];
                    var ce = domConstruct.toDom('<div class="esri-print__ce-' +
                      p +
                      '-info-container esri-print__form-section-container"><label>' +
                      p +
                      '<input type="text" class="esri-print__input-text esri-input" tabindex="0" data-input-name="ce-' +
                      p + '"></label></div>')
                    if (copyright) {
                      domConstruct.place(ce, copyright, 'after');
                    }
                    textNames.push(p);
                  }
                }
              }));
            }
          }, 200);
        }
      }

      function _bindEvents() {
        setTimeout(function () {
          var advBtn = query('.esri-print__advanced-options-button')[0];
          on(advBtn, 'click', function () {
            _addCustomEelements()
          });
          if(query('.esri-print__advanced-options-container')[0]){
            _addCustomEelements()
          }
        }, 200);
      }

      function _getLayoutTemplatesInfo() {
        var def = new Deferred();
        var parts = print.printServiceUrl.split('/');
        var pos = parts.indexOf('GPServer');
        if (pos > -1) {
          var url = null;
          if (/Utilities\/PrintingTools\/GPServer/.test(print.printServiceUrl)) {
            url = parts.slice(0, pos + 1).join('/') + '/' +
              encodeURIComponent('Get Layout Templates Info Task') + '/execute';
          } else {
            url = parts.slice(0, pos + 1).join('/') + '/' +
              encodeURIComponent('Get Layout Templates Info') + '/execute';
          }
          esriRequest(url, {
            query: {
              f: "json"
            },
            responseType: "json",
            timeout: 60000
          }).then(lang.hitch(this, function (info) {
            def.resolve(info);
          }), lang.hitch(this, function (err) {
            def.resolve({
              error: err
            });
          }));
        } else {
          def.resolve(null);
        }
        return def;
      }
    });
  </script>
</head>

<body class="calcite">
  <div id="viewDiv"></div>
</body>

</html>

View solution in original post

3 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Jason,

   No the 4.13 Print widget does not have builtin UI support for custom elements in print templates. To get this working you need to find the print services layout custom elements and add those to the advanced section of the widget. Borrowing some code from the WAB print I was able to come up with this modified sample. Just replace the print service url with one that has custom elements to see this work.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="initial-scale=1, maximum-scale=1,user-scalable=no"
    />
    <title>Print widget - 4.13</title>
    <link
      rel="stylesheet"
      href="https://js.arcgis.com/4.13/esri/themes/light/main.css"
    />

    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
        overflow: hidden;
      }
    </style>

    <script src="https://js.arcgis.com/4.13/"></script>
    <script>
      var print, templateInfos, layoutOptions;
      require([
        "esri/views/MapView",
        "esri/widgets/Print",
        "esri/WebMap",
        "dojo/aspect",
        "esri/request",
        "dojo/Deferred",
        "dojo/_base/lang",
        "dojo/dom-construct",
        "dojo/query",
        "dojo/_base/array",
        "dojo/on"
      ], function(MapView, Print, WebMap, aspect, esriRequest, Deferred, lang, domConstruct, query, array, on) {
        var webmap = new WebMap({
          portalItem: {
            // autocasts as new PortalItem()
            id: "d6d830a7184f4971b8a2f42cd774d9a7"
          }
        });

        var view = new MapView({
          container: "viewDiv",
          map: webmap
        });

        view.when(function() {
          print = new Print({
            view: view,
            // specify your own print service
            printServiceUrl:
              "https://utility.arcgisonline.com/arcgis/rest/services/Utilities/PrintingTools/GPServer/Export%20Web%20Map%20Task"
          });
          setTimeout(function(){
            var advBtn = query('.esri-print__advanced-options-button')[0];
            on(advBtn, 'click', function(){
              if(templateInfos){
                setTimeout(function(){
                  var templateInfo = templateInfos[0];
                  var customTextElements =  lang.getObject(
                    "layoutOptions.customTextElements",
                    false, templateInfo);
                    if (customTextElements && customTextElements.length > 0) {
                      var textNames = [];
                      array.forEach(customTextElements, lang.hitch(this, function(cte) {
                        for (var p in cte) {
                          if (textNames.indexOf(p) < 0) {
                            var advCont = query('.esri-print__advanced-options-container')[0];
                            var copyright = query('.esri-print__copyright-info-container')[0];
                            var ce = domConstruct.toDom('<div class="esri-print__ce-'+ p +'-info-container esri-print__form-section-container"><label>' + p + '<input type="text" class="esri-print__input-text esri-input" tabindex="0" data-input-name="ce-'+ p +'"></label></div>')
                            domConstruct.place(ce, copyright, 'after');
                            textNames.push(p);
                          }
                        }
                      }));
                    }
                }, 200);
              }
            });
            _getLayoutTemplatesInfo().then(function(result){
              var templatesInfo = result.data;
              if (templatesInfo && !templatesInfo.error) {
                var parameters = templatesInfo && templatesInfo.results;
                if (parameters && parameters.length > 0) {
                  array.some(parameters, lang.hitch(this, function(p) {
                    return p && p.paramName === 'Output_JSON' ?
                      templateInfos = p.value : false;
                  }));
                }
              }
            }).otherwise(function(err){
              console.info(err);
            });
          }, 500);

          // Add widget to the top right corner of the view
          view.ui.add(print, "top-right");

          aspect.around(print.viewModel, "print", function(originalPrint){
            return function(method, args){
              console.info(print.viewModel.templatesInfo)
              var deferred = originalPrint(method, args);
              //get the ce values.
              var ceInputs = query('.esri-print__input-text[data-input-name^=\"ce-\"]');
              console.info(ceInputs);
              var ceArr = [];
              ceInputs.forEach(function(cei){
                var ceProp = cei.dataset.inputName.replace('ce-','');
                var ceVal = cei.value;
                var ceObj = {};
                ceObj[ceProp] = ceVal;
                ceArr.push(ceObj);
              });
              method.layoutOptions.customTextElements = ceArr;
              return deferred;
            }
          });
        });
        
        function _getLayoutTemplatesInfo() {
          var def = new Deferred();
          var parts = print.printServiceUrl.split('/');
          var pos = parts.indexOf('GPServer');
          if (pos > -1) {
            var url = null;
            if (/Utilities\/PrintingTools\/GPServer/.test( print.printServiceUrl)) {
              url = parts.slice(0, pos + 1).join('/') + '/' +
                encodeURIComponent('Get Layout Templates Info Task') + '/execute';
            } else {
              url = parts.slice(0, pos + 1).join('/') + '/' +
                encodeURIComponent('Get Layout Templates Info') + '/execute';
            }
            esriRequest(url,{
              query: {
                f: "json"
              },
              responseType: "json",
              timeout: 60000
            }).then(lang.hitch(this, function(info) {
              def.resolve(info);
            }), lang.hitch(this, function(err) {
              def.resolve({
                error: err
              });
            }));
          } else {
            def.resolve(null);
          }
          return def;
        }
      });
    </script>
  </head>

  <body class="calcite">
    <div id="viewDiv"></div>
  </body>
</html>
JasonDavenport
New Contributor

Thanks! I have it working... except it prints the custom elements once. If I print again or click on the Map Only tab and click back, they do not show up on the print. Your thoughts? 

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Jason,

   Here is the update to fix those issues. Don't forget to mark this as the correct answer.

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
  <title>Print widget - 4.13</title>
  <link rel="stylesheet" href="https://js.arcgis.com/4.13/esri/themes/light/main.css" />

  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
      overflow: hidden;
    }
  </style>

  <script src="https://js.arcgis.com/4.13/"></script>
  <script>
    var print, templateInfos, layoutOptions;
    require([
      "esri/views/MapView",
      "esri/widgets/Print",
      "esri/WebMap",
      "dojo/aspect",
      "esri/request",
      "dojo/Deferred",
      "dojo/_base/lang",
      "dojo/dom-construct",
      "dojo/query",
      "dojo/_base/array",
      "dojo/on"
    ], function (MapView, Print, WebMap, aspect, esriRequest, Deferred, lang, domConstruct, query, array, on) {
      var webmap = new WebMap({
        portalItem: {
          // autocasts as new PortalItem()
          id: "d6d830a7184f4971b8a2f42cd774d9a7"
        }
      });

      var view = new MapView({
        container: "viewDiv",
        map: webmap
      });

      view.when(function () {
        print = new Print({
          view: view,
          // specify your own print service
          printServiceUrl: "https://gis.calhouncounty.org/arcgis3/rest/services/ExportWebMap/GPServer/Export_Web_Map"
        });

        print.viewModel.watch('state', function (s) {
          if (s === 'ready') {
            setTimeout(function () {
              var layoutTab = query('.esri-print__layout-tab')[0];
              on(layoutTab, 'click', function () {
                _bindEvents();
              });
              _bindEvents();
            }, 200);

            _getLayoutTemplatesInfo().then(function (result) {
              var templatesInfo = result.data;
              if (templatesInfo && !templatesInfo.error) {
                var parameters = templatesInfo && templatesInfo.results;
                if (parameters && parameters.length > 0) {
                  array.some(parameters, lang.hitch(this, function (p) {
                    return p && p.paramName === 'Output_JSON' ?
                      templateInfos = p.value : false;
                  }));
                }
              }
            }).otherwise(function (err) {
              console.info(err);
            });
          }
        });

        // Add widget to the top right corner of the view
        view.ui.add(print, "top-right");

        aspect.around(print.viewModel, "print", function (originalPrint) {
          return function (pt) {
            //get the ce values.
            var ceInputs = query('.esri-print__input-text[data-input-name^=\"ce-\"]');
            var ceArr = [];
            ceInputs.forEach(function (cei) {
              var ceProp = cei.dataset.inputName.replace('ce-', '');
              var ceVal = cei.value;
              var ceObj = {};
              ceObj[ceProp] = ceVal;
              ceArr.push(ceObj);
            });
            pt.layoutOptions.customTextElements = ceArr;
            var deferred = originalPrint(pt);
            return deferred;
          }
        });
      });

      function _addCustomEelements() {
        if (templateInfos) {
          query('.esri-print__input-text[data-input-name^=\"ce-\"]').forEach(function (cei) {
            domConstruct.destroy(cei);
          });
          setTimeout(function () {
            var layout = query('[data-target-property=\"layout\"]')[0];
            var templateInfo = templateInfos[layout.selectedIndex];
            var customTextElements = lang.getObject(
              "layoutOptions.customTextElements",
              false, templateInfo);
            if (customTextElements && customTextElements.length > 0) {
              var textNames = [];
              array.forEach(customTextElements, lang.hitch(this, function (cte) {
                for (var p in cte) {
                  if (textNames.indexOf(p) < 0) {
                    var advCont = query(
                      '.esri-print__advanced-options-container')[0];
                    var copyright = query(
                      '.esri-print__copyright-info-container')[0];
                    var ce = domConstruct.toDom('<div class="esri-print__ce-' +
                      p +
                      '-info-container esri-print__form-section-container"><label>' +
                      p +
                      '<input type="text" class="esri-print__input-text esri-input" tabindex="0" data-input-name="ce-' +
                      p + '"></label></div>')
                    if (copyright) {
                      domConstruct.place(ce, copyright, 'after');
                    }
                    textNames.push(p);
                  }
                }
              }));
            }
          }, 200);
        }
      }

      function _bindEvents() {
        setTimeout(function () {
          var advBtn = query('.esri-print__advanced-options-button')[0];
          on(advBtn, 'click', function () {
            _addCustomEelements()
          });
          if(query('.esri-print__advanced-options-container')[0]){
            _addCustomEelements()
          }
        }, 200);
      }

      function _getLayoutTemplatesInfo() {
        var def = new Deferred();
        var parts = print.printServiceUrl.split('/');
        var pos = parts.indexOf('GPServer');
        if (pos > -1) {
          var url = null;
          if (/Utilities\/PrintingTools\/GPServer/.test(print.printServiceUrl)) {
            url = parts.slice(0, pos + 1).join('/') + '/' +
              encodeURIComponent('Get Layout Templates Info Task') + '/execute';
          } else {
            url = parts.slice(0, pos + 1).join('/') + '/' +
              encodeURIComponent('Get Layout Templates Info') + '/execute';
          }
          esriRequest(url, {
            query: {
              f: "json"
            },
            responseType: "json",
            timeout: 60000
          }).then(lang.hitch(this, function (info) {
            def.resolve(info);
          }), lang.hitch(this, function (err) {
            def.resolve({
              error: err
            });
          }));
        } else {
          def.resolve(null);
        }
        return def;
      }
    });
  </script>
</head>

<body class="calcite">
  <div id="viewDiv"></div>
</body>

</html>