Issues importing ArcGIS Javascript API resources and loading dojo
I am using the ArcGIS Javascript API to add some functionality (a search widget) to an existing web app using AngularJS and JSP. I am having issues resolving a pathname for the esri/dijit/Search package, as it attempts a pathname on our local server instead of the online API and produces a 404 error.
EDIT I am seeing now that if I reference the online ArcGIS Javascript API, I have a local file that receives the 404 error. Not referencing it, of course, causes issues for the esri/dijit/Search file. I am focusing now on configuring this so that I can resolve both pathnames. Updated code is below in edit section.
I have an app.js with the require function:
'use strict';
var mapApp=angular.module('org.ours.app.map', ['ngRoute','org.ours.app.map.controllers']);
mapApp.config(['$routeProvider', function($routeProvider,StudentController) {
$routeProvider.when('/', { controller: 'MapController'});
$routeProvider.otherwise({redirectTo: '/'});
}]);
require([
"esri/map",
"dojo/domReady!",
"esri/toolbars/navigation",
"esri/toolbars/draw",
"esri/layers/ArcGISDynamicMapServiceLayer",
"esri/tasks/IdentifyParameters",
"esri/tasks/IdentifyResult",
"esri/tasks/IdentifyTask",
"esri/layers/GraphicsLayer",
"esri/dijit/InfoWindow",
"esri/dijit/Search",
"esri/layers/FeatureLayer",
"esri/InfoTemplate"
], function () {
var lScope=angular.element(document.getElementById('mapDiv')).scope();
lScope.onReady.apply(lScope,arguments);
});
The controller for the Search widget (adapted from an online ArcGIS sample):
'use strict';
mapAppControllers.controller('SearchController', function($rootScope, $scope) {
$scope.$parent.searchScope=$scope;
var me=$scope;
var ALL;
angular.extend($scope,{
init:function(Map, Search, FeatureLayer, InfoTemplate, pMap){
me.map=pMap;
me.search = new Search({
enableButtonMode: true, //this enables the search widget to display as a single button
enableLabel: false,
enableInfoWindow: true,
showInfoWindowOnSelect: false,
map: map
}, "search");
me.sources = search.get("sources");
sources.push({
featureLayer: new FeatureLayer("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/US_Senators/FeatureServer/0"),
searchFields: ["Name"],
displayField: "Name",
exactMatch: false,
name: "Senator",
outFields: ["*"],
placeholder: "Senator name",
maxResults: 6,
maxSuggestions: 6,
//Create an InfoTemplate
infoTemplate: new InfoTemplate("Senator information", "Name: ${Name}</br>State: ${State}</br>Party Affiliation: ${Party}</br>Phone No: ${Phone_Number}<br><a href=${Web_Page} target=_blank ;'>Website</a>"),
enableSuggestions: true,
minCharacters: 0
});
//Set the sources above to the search widget
search.set("sources", sources);
search.startup();
}
})
});
I then have an index.jsp with a few map elements including the Search widget (on the bottom) that I am attempting to add. I've referenced the online ArcGIS Javascript API here, but I am not sure it's in the right place. I am also wondering if there may be another package that is rerouting the /esri/dijit/Search file.
This version creates a 404 error that looks for the file in http://ouserver/esri/dijit/Search:
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!doctype html>
<html ng-app="org.ours.app.map" class="map-viewport">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="js/arcgis/esri/css/esri.css">
<link rel="stylesheet" href="css/bootstrap/bootstrap.css">
<link rel="stylesheet" href="css/bootstrap/bootstrap-theme.css">
<link rel="stylesheet" href="css/map.css">
<script src="js/arcgis/dojo/dojo.js" data-dojo-config="async: true"></script>
<script src="js/angularjs/angular.min.js"></script>
<script src="js/angularjs/i18n/angular-locale_fr-fr.js"></script>
<script src="js/angularjs/angular-animate.min.js"></script>
<script src="js/angularjs/angular-route.min.js"></script>
<script src="js/bootstrap/ui-bootstrap-tpls-1.1.2.min.js"></script>
<script src="js/utils/ColorsUtil.js"></script>
<script src="js/controllers.js"></script>
<script src="js/controllers/Attributes.js"></script>
<script src="js/controllers/Results.js"></script>
<script src="js/controllers/Identify.js"></script>
<script src="js/controllers/Toolbar.js"></script>
<script src="js/controllers/MapService.js"></script>
<script src="js/controllers/Map.js"></script>
<script src="js/controllers/Body.js"></script>
<script src="js/controllers/Search.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-controller="BodyController" class="map-body">
<div style="display: none" ng-controller="IdentifyController"></div>
<div id="mapDiv" ng-controller="MapController">
<script type="text/ng-template" id="infoWindowTemplate.html">
<div style="max-height: 300px;overflow-y: auto;overflow-x: hidden">
<table cellpadding="2">
<tbody>
<tr ng-repeat="attribute in resultsScope.popover.attributes" ng-class="$index%2==1?'map-attributes-even':''" >
<td style="font-weight: bold" >{{attribute.label}}</td>
<td style="padding-left: 5px" uib-tooltip="{{attribute.value}}">{{attribute.value}}</td>
</tr>
</tbody>
</table>
</div>
</script>
<div id="popoverPosition"
popover-title="{{resultsScope.popover.title}}"
uib-popover-template="resultsScope.popover.templateUrl"
popover-is-open="resultsScope.popover.isOpen"
></div>
</div>
<div class="map-toolbar" ng-controller="ToolbarController" id="toolbar">
<div class="btn-group">
<label class="btn btn-primary" ng-click="onMapActionClick('prev')" ng-disabled="navModel.prev" uib-tooltip="Vue précédente" tooltip-placement="bottom"><i class="glyphicon glyphicon-circle-arrow-left"></i></label>
<label class="btn btn-primary" ng-model="mapTool" uib-btn-radio="'pan'" uib-tooltip="Déplacer" tooltip-placement="bottom"><i class="glyphicon glyphicon-move"></i></label>
<label class="btn btn-primary" ng-click="onMapActionClick('next')" ng-disabled="navModel.next" uib-tooltip="Vue suivante" tooltip-placement="bottom"><i class="glyphicon glyphicon-circle-arrow-right"></i></label>
</div>
<div class="btn-group">
<label class="btn btn-primary" ng-model="mapTool" uib-btn-radio="'zoomout'" uib-tooltip="Dézoomer" tooltip-placement="bottom"><i class="glyphicon glyphicon-zoom-out"></i></label>
<label class="btn btn-primary" ng-click="onMapActionClick('full')" uib-tooltip="Vue globale" tooltip-placement="bottom"><i class="glyphicon glyphicon-fullscreen"></i></label>
<label class="btn btn-primary" ng-model="mapTool" uib-btn-radio="'zoomin'" uib-tooltip="Zoomer" tooltip-placement="bottom"><i class="glyphicon glyphicon-zoom-in"></i></label>
</div>
<div class="btn-group">
<label class="btn btn-primary" ng-model="mapTool" uib-btn-radio="'identify'" uib-tooltip="Identifier" tooltip-placement="bottom"><i class="glyphicon glyphicon-info-sign"></i></label>
</div>
<div class="btn-group" style="display: inline-block;width:400px" ng-controller="MapServiceController">
<script type="text/ng-template" id="serviceLyerTemplate.html">
<a>
<span ng-bind-html="match.label | uibTypeaheadHighlight:query | BoldLayersOptions:match"></span>
</a>
</script>
<div style="display: inline-block;" >
<input type="text" ng-model="serviceSelected" placeholder="Selectionner un service" uib-typeahead="service as service.name for service in services | filter:{name:$viewValue}"
typeahead-template-url="serviceLyerTemplate.html" class="form-control" typeahead-show-hint="true" typeahead-min-length="0" style="display: inline-block;"
typeahead-on-select="onServiceSelect($model)" typeahead-select-on-blur="true">
</div>
<div style="display: inline-block;width:50%">
<input type="text" ng-model="layerSelected" placeholder="Selectionner une couche" uib-typeahead="layer as layer.name for layer in layers | filter:{name:$viewValue}"
typeahead-template-url="serviceLyerTemplate.html" class="form-control" typeahead-show-hint="true" typeahead-min-length="0" style="display: inline-block;"
typeahead-on-select="onLayerSelect($model)" typeahead-select-on-blur="true"
>
</div>
</div>
</div>
<div class="map-messagebar">
<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)" style="width: 600px">{{alert.msg}}</uib-alert>
</div>
<label class="btn btn-success map-identify" ng-model="resultsScope.visible" uib-btn-checkbox ng-click="attributesScope.visible=$event.ctrlKey?resultsScope.visible:attributesScope.visible"><i class="glyphicon glyphicon-info-sign"></i></label>
<label class="btn btn-success map-show-attributes" ng-model="attributesScope.visible" uib-btn-checkbox ng-click="resultsScope.visible=$event.ctrlKey?attributesScope.visible:resultsScope.visible"><i class="glyphicon glyphicon-list-alt"></i></label>
<button class="btn btn-success map-reset" ng-click="reset()"><i class="glyphicon glyphicon-remove-sign"></i></button>
<div class="panel panel-primary map-results animate-hide" id="resultsDiv" ng-controller="ResultsController" ng-show="visible">
<div class="panel-heading"><i class="glyphicon glyphicon-info-sign"></i> Résultats<i class="pull-right glyphicon glyphicon-chevron-left" ng-click="visible=!visible"></i></div>
<div class="panel-body map-results-body" >
<uib-accordion close-others="oneAtATime" style="width: 100%;height: 100%">
<uib-accordion-group ng-repeat="layer in layers" is-open="layer.isFirstOpen" class="panel panel-success">
<uib-accordion-heading><i class="glyphicon glyphicon-play" ng-style="layer.style"></i> {{layer.name}}</uib-accordion-heading>
<label class="btn btn-link btn-default map-result" ng-model="result.visible" ng-click="show(result)" ng-repeat="result in layer.results" uib-btn-checkbox>
{{result.displayValue}}
<i class="pull-right glyphicon glyphicon-fullscreen" ng-click="zoom(result,$event)"></i>
<i class="pull-right glyphicon glyphicon-list-alt" ng-click="attributesScope.visible=true;attributesScope.show(result,$event)" style="margin-right:5px"></i>
</label>
</uib-accordion-group>
</uib-accordion>
</div>
</div>
<div class="panel panel-primary map-attributes" id="attributesDiv" ng-controller="AttributesController" ng-show="visible">
<div class="panel-heading"><i class="glyphicon glyphicon-list-alt"></i> Attributs<i class="pull-right glyphicon glyphicon-chevron-right" ng-click="visible=!visible"></i></div>
<div class="panel-body map-attributes-body">
<table cellpadding="2">
<tbody>
<tr ng-repeat="attribute in attributes" ng-class="$index%2==1?'map-attributes-even':''" ><td style="font-weight: bold">{{attribute.label}}</td><td style="padding-left: 5px">{{attribute.value}}</td></tr>
</tbody>
</table>
</div>
</div>
<script src="https://js.arcgis.com/3.17/"></script>
<div ng-controller="SearchController" id="search">
<h1> This is a test </h1>
</div>
</body>
</html>
There are many other files in the package. I'm new to this, so I am open to suggestions on where to look. This is the file structure:
EDIT When moving the ArcGIS API reference to the top of index.jsp, I now have issues resolving dojo_fr.js (on local server). How can I configure this so that both are resolved?
This version creates a 404 error looking for the file in https://js.arcgis.com/3.17/dojo/nls/dojo_fr.js:
<%@ page contentType="text/html;charset=UTF-8" language="java" %><!doctype html>
<html ng-app="pf.pde.app.map" class="map-viewport">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="js/arcgis/esri/css/esri.css">
<link rel="stylesheet" href="css/bootstrap/bootstrap.css">
<link rel="stylesheet" href="css/bootstrap/bootstrap-theme.css">
<link rel="stylesheet" href="css/map.css">
<script src="https://js.arcgis.com/3.17/"></script>
<script src="js/arcgis/dojo/dojo.js" data-dojo-config="async: true"></script>
<script src="js/angularjs/angular.min.js"></script>
<script src="js/angularjs/i18n/angular-locale_fr-fr.js"></script>
<script src="js/angularjs/angular-animate.min.js"></script>
<script src="js/angularjs/angular-route.min.js"></script>
<script src="js/bootstrap/ui-bootstrap-tpls-1.1.2.min.js"></script>
<script src="js/utils/ColorsUtil.js"></script>
<script src="js/controllers.js"></script>
<script src="js/controllers/Attributes.js"></script>
<script src="js/controllers/Results.js"></script>
<script src="js/controllers/Identify.js"></script>
<script src="js/controllers/Toolbar.js"></script>
<script src="js/controllers/MapService.js"></script>
<script src="js/controllers/Map.js"></script>
<script src="js/controllers/Body.js"></script>
<script src="js/controllers/Search.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-controller="BodyController" class="map-body">
<div style="display: none" ng-controller="IdentifyController"></div>
<div id="mapDiv" ng-controller="MapController">
<script type="text/ng-template" id="infoWindowTemplate.html">
<div style="max-height: 300px;overflow-y: auto;overflow-x: hidden">
<table cellpadding="2">
<tbody>
<tr ng-repeat="attribute in resultsScope.popover.attributes" ng-class="$index%2==1?'map-attributes-even':''" >
<td style="font-weight: bold" >{{attribute.label}}</td>
<td style="padding-left: 5px" uib-tooltip="{{attribute.value}}">{{attribute.value}}</td>
</tr>
</tbody>
</table>
</div>
</script>
<div id="popoverPosition"
popover-title="{{resultsScope.popover.title}}"
uib-popover-template="resultsScope.popover.templateUrl"
popover-is-open="resultsScope.popover.isOpen"
></div>
</div>
<div class="map-toolbar" ng-controller="ToolbarController" id="toolbar">
<div class="btn-group">
<label class="btn btn-primary" ng-click="onMapActionClick('prev')" ng-disabled="navModel.prev" uib-tooltip="Vue précédente" tooltip-placement="bottom"><i class="glyphicon glyphicon-circle-arrow-left"></i></label>
<label class="btn btn-primary" ng-model="mapTool" uib-btn-radio="'pan'" uib-tooltip="Déplacer" tooltip-placement="bottom"><i class="glyphicon glyphicon-move"></i></label>
<label class="btn btn-primary" ng-click="onMapActionClick('next')" ng-disabled="navModel.next" uib-tooltip="Vue suivante" tooltip-placement="bottom"><i class="glyphicon glyphicon-circle-arrow-right"></i></label>
</div>
<div class="btn-group">
<label class="btn btn-primary" ng-model="mapTool" uib-btn-radio="'zoomout'" uib-tooltip="Dézoomer" tooltip-placement="bottom"><i class="glyphicon glyphicon-zoom-out"></i></label>
<label class="btn btn-primary" ng-click="onMapActionClick('full')" uib-tooltip="Vue globale" tooltip-placement="bottom"><i class="glyphicon glyphicon-fullscreen"></i></label>
<label class="btn btn-primary" ng-model="mapTool" uib-btn-radio="'zoomin'" uib-tooltip="Zoomer" tooltip-placement="bottom"><i class="glyphicon glyphicon-zoom-in"></i></label>
</div>
<div class="btn-group">
<label class="btn btn-primary" ng-model="mapTool" uib-btn-radio="'identify'" uib-tooltip="Identifier" tooltip-placement="bottom"><i class="glyphicon glyphicon-info-sign"></i></label>
</div>
<div class="btn-group" style="display: inline-block;width:400px" ng-controller="MapServiceController">
<script type="text/ng-template" id="serviceLyerTemplate.html">
<a>
<span ng-bind-html="match.label | uibTypeaheadHighlight:query | BoldLayersOptions:match"></span>
</a>
</script>
<div style="display: inline-block;" >
<input type="text" ng-model="serviceSelected" placeholder="Selectionner un service" uib-typeahead="service as service.name for service in services | filter:{name:$viewValue}"
typeahead-template-url="serviceLyerTemplate.html" class="form-control" typeahead-show-hint="true" typeahead-min-length="0" style="display: inline-block;"
typeahead-on-select="onServiceSelect($model)" typeahead-select-on-blur="true">
</div>
<div style="display: inline-block;width:50%">
<input type="text" ng-model="layerSelected" placeholder="Selectionner une couche" uib-typeahead="layer as layer.name for layer in layers | filter:{name:$viewValue}"
typeahead-template-url="serviceLyerTemplate.html" class="form-control" typeahead-show-hint="true" typeahead-min-length="0" style="display: inline-block;"
typeahead-on-select="onLayerSelect($model)" typeahead-select-on-blur="true"
>
</div>
</div>
</div>
<div class="map-messagebar">
<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)" style="width: 600px">{{alert.msg}}</uib-alert>
</div>
<label class="btn btn-success map-identify" ng-model="resultsScope.visible" uib-btn-checkbox ng-click="attributesScope.visible=$event.ctrlKey?resultsScope.visible:attributesScope.visible"><i class="glyphicon glyphicon-info-sign"></i></label>
<label class="btn btn-success map-show-attributes" ng-model="attributesScope.visible" uib-btn-checkbox ng-click="resultsScope.visible=$event.ctrlKey?attributesScope.visible:resultsScope.visible"><i class="glyphicon glyphicon-list-alt"></i></label>
<button class="btn btn-success map-reset" ng-click="reset()"><i class="glyphicon glyphicon-remove-sign"></i></button>
<div class="panel panel-primary map-results animate-hide" id="resultsDiv" ng-controller="ResultsController" ng-show="visible">
<div class="panel-heading"><i class="glyphicon glyphicon-info-sign"></i> Résultats<i class="pull-right glyphicon glyphicon-chevron-left" ng-click="visible=!visible"></i></div>
<div class="panel-body map-results-body" >
<uib-accordion close-others="oneAtATime" style="width: 100%;height: 100%">
<uib-accordion-group ng-repeat="layer in layers" is-open="layer.isFirstOpen" class="panel panel-success">
<uib-accordion-heading><i class="glyphicon glyphicon-play" ng-style="layer.style"></i> {{layer.name}}</uib-accordion-heading>
<label class="btn btn-link btn-default map-result" ng-model="result.visible" ng-click="show(result)" ng-repeat="result in layer.results" uib-btn-checkbox>
{{result.displayValue}}
<i class="pull-right glyphicon glyphicon-fullscreen" ng-click="zoom(result,$event)"></i>
<i class="pull-right glyphicon glyphicon-list-alt" ng-click="attributesScope.visible=true;attributesScope.show(result,$event)" style="margin-right:5px"></i>
</label>
</uib-accordion-group>
</uib-accordion>
</div>
</div>
<div class="panel panel-primary map-attributes" id="attributesDiv" ng-controller="AttributesController" ng-show="visible">
<div class="panel-heading"><i class="glyphicon glyphicon-list-alt"></i> Attributs<i class="pull-right glyphicon glyphicon-chevron-right" ng-click="visible=!visible"></i></div>
<div class="panel-body map-attributes-body">
<table cellpadding="2">
<tbody>
<tr ng-repeat="attribute in attributes" ng-class="$index%2==1?'map-attributes-even':''" ><td style="font-weight: bold">{{attribute.label}}</td><td style="padding-left: 5px">{{attribute.value}}</td></tr>
</tbody>
</table>
</div>
</div>
<div ng-controller="SearchController" id="search">
<h1> This is a test </h1>
</div>
</body>
</html>
UPDATE I'm trying to do the dojoConfig, but I am still not getting it (see how it currently is below). There are other things that are keeping the page from loading as well. When these things are eliminated, the page loads and the rest works :
-ArcGIS API online reference (404 error on dojo_fr.js) -requiring esri/Search/dijit (404 error on Search.js if ArcGIS API is not referenced the way I've done it below)
<script src="https://js.arcgis.com/3.17/"></script>
<!-- First dojoConfig -->
<script type="text/javascript">
var dojoConfig = {
packages: [
{
location: '/js/arcgis',
name: 'arcgis'
}
]
};
</script>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<script src="js/arcgis/dojo/dojo.js" data-dojo-config="async: true"></script>
I think what you need is Configuring Dojo with dojoConfig as i don't see it in your code. Basically you need to create the dojoConfig
var before including dojo
, for example:
<!-- If including dojo from googleapis -->
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
<!-- And later do this -->
<script type="text/javascript">
require([
'myApp/myComponent',
'dojo/dom',
'dojo/dom-construct'
], function(myComponent, dom, domConstruct) {
//do something
});
</script>
Loading myApp/myComponent
will fail because the loader will use this url
http://ajax.googleapis.com/ajax/libs/dojo/1.10.4/myApp/myComponent.js
but, if before including dojo
we initiate the dojoConfig
<!-- First dojoConfig -->
<script type="text/javascript">
var dojoConfig = {
packages: [
{
location: '/js/myApp',
name: 'myApp'
}
]
};
</script>
<!-- Then load dojo -->
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>
Then the loader will try to get myApp/myComponent
from my local server.
Note that this is an illustrative example of how you can use the dojoContig
.
上一篇: Xcode中的Storyboard非常慢