How do I use esriRequest in a widget?

5065
4
Jump to solution
11-09-2015 02:09 PM
MathiasKP
New Contributor

Hello, can anyone guide me in a direction on how to use the esriRequest function in a Web Appbuilder Widget?

I have just started using Web AppBuilder Developer Edition. I started with extending the sample widget Demo with a button

Widget.html:

<div>
<button id="gotoPosition" data-dojo-type="dijit/form/Button" type="button" data-dojo-attach-point="gotoPosition">Go to position</button>
</div>

I then extended the onOpen: function() in widget.js to zoom to a position

  ...
 onOpen: function(){
  console.log('onOpen');
  var map = this.map;
  var Long, Lat;
  var LocPoint, point;   
  //Go to position
  on(this.gotoPosition, 'click', lang.hitch(this, function(evt){   
    console.log('gotoPosition 2');
    map.graphics.clear();
    Lat = 55;
    Long = 15;
    LocPoint = new Point([Long,Lat]);
    map.centerAndZoom(LocPoint,17);
    }));
  },
...

From Access data (XML) | ArcGIS API for JavaScript I found out how to use esriRequest and from Using the proxy | Guide | ArcGIS API for JavaScript how to install the proxy and finally putting it all together in one HTML file (esriRequest_xml.html) which works fine.

<!DOCTYPE html>
<html>
<head>
  <title>XML Content</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <link rel="stylesheet" href="http://js.arcgis.com/3.14/esri/css/esri.css">
  
  <script src="http://js.arcgis.com/3.13/"></script>
  <script>
    require(["dojo/dom", "dojo/on", "dojo/dom-class", "dojo/_base/json", "dojox/xml/parser", "esri/config", "esri/request", "dojo/domReady!"], function(dom, on, domClass, dojoJson, xmlParser, esriConfig, esriRequest) {
      console.log('ok')
      esriConfig.defaults.io.proxyUrl = "/PHP_proxy/proxy.php";
      var url = "url to a xml docement";
      var requestHandle = esriRequest({
        "url": url,
        "handleAs": "xml"
      });
      requestHandle.then(requestSucceeded, requestFailed);
      function requestSucceeded(response, io){
        document.write("Succes");
        //do something with the xml data
      }
      function requestFailed(error, io){
        document.write("Fail");
      }
    });
  </script>
</head>
<body>
  </body>
</html>

I then tried to put the javascript code from esriRequest_xml.html into the onOpen: function()  but this resulted in the error "Uncaught TypeError: Cannot read property 'io' of undefined" Maybe because of wrong scope?, but don't know how to fix this. Can anyone guide me how to get esriRequest to work?

Tags (1)
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Mathias,

  Try this:

define([
  /*rearranged your requires two where out of place and domReady should always be last*/
  'dojo/_base/declare',
  'jimu/BaseWidget',
  "dojo/on",
  'dojo/_base/lang',
  "esri/graphic", 
  "esri/geometry/Point",
  "dojo/dom",
  "dojo/data/ItemFileReadStore",
  "dijit/form/ComboBox",
  "dojo/_base/json",
  "dojo/dom-class",
  "dojox/xml/parser",
  "esri/config",
  "esri/request",
  "dojo/domReady!"
  ],

function(
  declare,
  BaseWidget,
  on,
  lang,
  Graphic,
  Point,
  dom,
  ItemFileReadStore,
  ComboBox,
  dojoJson,
  domClass,
  xmlParser,
  esriConfig,
  esriRequest
) {

  //To create a widget, you need to derive from BaseWidget.
  return declare([BaseWidget], {
    // DemoWidget code goes here
    baseClass: 'jimu-widget-demo',

    postCreate: function() {
      this.inherited(arguments);
      console.log('postCreate');
    },

    startup: function() {
      this.inherited(arguments);
      console.log('startup');
      //ComboBox til Ejerlavnavn
      /*var store;
      store = new ItemFileReadStore({ url: "ejerlav.json" }); 
      var combo = new ComboBox({ 
        store: store,
        pageSize: "10" 
      }, 
      dom.byId('EjerlavComboBox')); 
      combo.startup();*/
    },
        
    onOpen: function(){
      console.log('onOpen');
      var map = this.map;
      var Long, Lat;
      var LocPoint, point;
      
     //Go to position
      on(this.gotoPosition, 'click', lang.hitch(this, function(evt){ 
        console.log('gotoPosition ');
        map.graphics.clear();
//WAB already handles the proxy for you so this is not needed        
        //This line creates the error: Uncaught TypeError: Cannot read property 'io' of undefined
        //esriConfig.defaults.io.proxyUrl = "/PHP_proxy/proxy.php";
        var url = "your xml url";
        var requestHandle = esriRequest({
          "url": url,
          "handleAs": "xml"
        });
        requestHandle.then(requestSucceeded, requestFailed);
        
        function requestSucceeded(response, io){
          //do something with the xml data
          console.info(response, io);
        }
        
        function requestFailed(error, io){
          console.info(error, io);
        }

        //Lat = this.EjerlavTextBox.value;
        //Long = this.MatrNrTextBox.value;
        Lat = 55;
        Long = 15;
        LocPoint = new Point([Long,Lat]);
        map.centerAndZoom(LocPoint,17);
      }));
    },

    onClose: function(){
      console.log('onClose');
    },

    onMinimize: function(){
      console.log('onMinimize');
    },

    onMaximize: function(){
      console.log('onMaximize');
    },

    onSignIn: function(credential){
      /* jshint unused:false*/
      console.log('onSignIn');
    },

    onSignOut: function(){
      console.log('onSignOut');
    }
  });
});

View solution in original post

0 Kudos
4 Replies
RobertScheitlin__GISP
MVP Emeritus

Mathias,

  Try this:

define([
  /*rearranged your requires two where out of place and domReady should always be last*/
  'dojo/_base/declare',
  'jimu/BaseWidget',
  "dojo/on",
  'dojo/_base/lang',
  "esri/graphic", 
  "esri/geometry/Point",
  "dojo/dom",
  "dojo/data/ItemFileReadStore",
  "dijit/form/ComboBox",
  "dojo/_base/json",
  "dojo/dom-class",
  "dojox/xml/parser",
  "esri/config",
  "esri/request",
  "dojo/domReady!"
  ],

function(
  declare,
  BaseWidget,
  on,
  lang,
  Graphic,
  Point,
  dom,
  ItemFileReadStore,
  ComboBox,
  dojoJson,
  domClass,
  xmlParser,
  esriConfig,
  esriRequest
) {

  //To create a widget, you need to derive from BaseWidget.
  return declare([BaseWidget], {
    // DemoWidget code goes here
    baseClass: 'jimu-widget-demo',

    postCreate: function() {
      this.inherited(arguments);
      console.log('postCreate');
    },

    startup: function() {
      this.inherited(arguments);
      console.log('startup');
      //ComboBox til Ejerlavnavn
      /*var store;
      store = new ItemFileReadStore({ url: "ejerlav.json" }); 
      var combo = new ComboBox({ 
        store: store,
        pageSize: "10" 
      }, 
      dom.byId('EjerlavComboBox')); 
      combo.startup();*/
    },
        
    onOpen: function(){
      console.log('onOpen');
      var map = this.map;
      var Long, Lat;
      var LocPoint, point;
      
     //Go to position
      on(this.gotoPosition, 'click', lang.hitch(this, function(evt){ 
        console.log('gotoPosition ');
        map.graphics.clear();
//WAB already handles the proxy for you so this is not needed        
        //This line creates the error: Uncaught TypeError: Cannot read property 'io' of undefined
        //esriConfig.defaults.io.proxyUrl = "/PHP_proxy/proxy.php";
        var url = "your xml url";
        var requestHandle = esriRequest({
          "url": url,
          "handleAs": "xml"
        });
        requestHandle.then(requestSucceeded, requestFailed);
        
        function requestSucceeded(response, io){
          //do something with the xml data
          console.info(response, io);
        }
        
        function requestFailed(error, io){
          console.info(error, io);
        }

        //Lat = this.EjerlavTextBox.value;
        //Long = this.MatrNrTextBox.value;
        Lat = 55;
        Long = 15;
        LocPoint = new Point([Long,Lat]);
        map.centerAndZoom(LocPoint,17);
      }));
    },

    onClose: function(){
      console.log('onClose');
    },

    onMinimize: function(){
      console.log('onMinimize');
    },

    onMaximize: function(){
      console.log('onMaximize');
    },

    onSignIn: function(credential){
      /* jshint unused:false*/
      console.log('onSignIn');
    },

    onSignOut: function(){
      console.log('onSignOut');
    }
  });
});
0 Kudos
MathiasKP
New Contributor

Hi Robert, thank you very much it works now

I can see you moved "dojo/domReady! to the end of the define list. Was this what caused my problem?

But if I want to access xml documents from at different domain I still need the line esriConfig.defaults.io.proxyUrl = "/PHP_proxy/proxy.php"; If I remove the line I get the error: "esri.config.defaults.io.proxyUrl is not set.  If making a request to a CORS enabled server, please push the domain into esri.config.defaults.io.corsEnabledServers". You mentioned that WAB takes care of this for me, but not in my case. Should I some where in other Web AppBuilder files configure this?

/Mathias

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Mathias,

  Yes it was the issue with the location of the domReady in your code that threw off the synchronization of your requires and your vars. WAB has a NodeJS proxy setup when you are working in builder. Once you deploy your app then you have to setup a proxy if you are going to use one and specify its url in the main config.json If you need to use a specific proxy while in builder for your app then you can set it in the main config.json for that app just like you would when you deploy the app. Open your apps config.json (i.e. [install dir]\server\apps\[app#]\config.json). Scroll to the bottom of that file and find this section:

"httpProxy": {
    "useProxy": true,
    "url": "/proxy.js"
  },

and change it to:

"httpProxy": {
    "useProxy": true,
    "url": "/PHP_proxy/proxy.php"
  },
MathiasKP
New Contributor

Robert

I never would have thought that the position of domReady was the problem, but now I know that. I got it to work fine with adding the proxy to config.json.

Thank you very much for your help.

/Mathias

0 Kudos