You are on page 1of 58

Declarative Mapping Applications

with AngularJS
Dave Bouwman - @dbouwman
Tom Wayson - @TomWayson
Angular
<declarative />
{{data-binding}}
test-all-the-things
dependency injection
super popular
big ecosystem
“forms-over-data”
Not So Much…
Big in “the enterprise”

“enterprise”
Big in “the enterprise”

Visual Studio Tools


Choosing a JS Framework
Friday 1pm Primrose B
ng @ Esri
maps are awesome

80497449@N04/8280671002
component in a system

no3rdw/4731781962
adding maps to ng-apps

no3rdw/4731781962
<directive>
Wrap Angular in Dojo
Make JSAPI work in Angular
<esri-map id="map" center="map.center" zoom="map.zoom" basemap="topo">
<esri-feature-layer url="http://services.arcgis.com/.../FeatureServer/0" />
<esri-feature-layer url="http://services.arcgis.com/.../FeatureServer/1" />
</esri-map>
<esri-map id="map" center="map.center" zoom="map.zoom" basemap="topo">
<esri-feature-layer url="http://services.arcgis.com/.../FeatureServer/0" />
<esri-feature-layer url="http://services.arcgis.com/.../FeatureServer/1" />
</esri-map>

Map Directive
Let’s go further…
<esri-map id="map" center="map.center" zoom="map.zoom" basemap="topo">
<esri-feature-layer url="http://services.arcgis.com/.../FeatureServer/0" />
<esri-feature-layer url="http://services.arcgis.com/.../FeatureServer/1">
<renderer field="area" type="class-breaks">
<break min="0" max="50">
<symbol linecolor="#ff0044" fillcolor="#ff0044">
</break>
<break min="51" max="150">
<symbol linecolor="#cc0044" fillcolor="#cc0044">
</break>
<break min="151" max="500">
<symbol linecolor="#aa0044" fillcolor="#aa0044">
</break>
</renderer></esri-feature-layer>
</esri-map>
<esri-map id="map" center="map.center" zoom="map.zoom" basemap="topo">
<esri-feature-layer url="http://services.arcgis.com/.../FeatureServer/0" />

25 types of layers
<esri-feature-layer url="http://services.arcgis.com/.../FeatureServer/1">
<renderer field="area" type="class-breaks">
<break min="0" max="50">

10 renderers
<symbol linecolor="#ff0044" fillcolor="#ff0044">
</break>
<break min="51" max="150">

9 types of symbols
<symbol linecolor="#cc0044" fillcolor="#cc0044">
</break>
<break min="151" max="500">

100s of events
<symbol linecolor="#aa0044" fillcolor="#aa0044">
</break>
</renderer></esri-feature-layer>
</esri-map>
It’s… It’s… XML??!
Directives exposing the entire
Esri JS API?

No.
Directives exposing the entire
Esri Leaflet API?

No.
Facilitate creating custom
directives?

Yes!
What do you need?
http://github.com/esri/angular-esri-map
esri angular-esri-map
angular-esri-map: How does it work?

<script type="text/javascript" src="http://js.arcgis.com/3.12compact"></script>


<script src="libs/angularjs/1.2.16/angular.js"></script>
<script src="libs/angular-esri-map.js"></script>

<script type="text/javascript">
angular.module('app', ['esri.map']);
</script>

See the Quick Start


angular-esri-map: Using the Directives

<esri-map id="map" center="map.center" zoom="map.zoom" basemap="topo"> </esri-map>

angular.module('app').controller('MyController', function($scope) {
$scope.map = {
center: { lng: -122.45, lat: 37.75 },
zoom: 13
};
});

See the Examples


Building Apps
Real World App: Facilities Management Application

Regional View of Sites

Floor Plan Map

Site Map
Real World App: Gap Analysis
Layer Visibility Renderer
Definition Query

Layer Selection

Feature Layers

Get Layer Features Map Legend


Option 1: Use the Backdoor

<esri-map id="floorPlan" center="map.center" zoom="map.zoom"


load="mapLoaded">
<esri-feature-layer title=“Floor Plan Lines" url="..."></esri-feature-
layer>
<esri-feature-layer title=“Spaces" url="..."></esri-feature-layer>
<div esri-legend target-id="legend"></div>
$scope.mapLoaded
</esri-map> = function(map) {
// get references to the feature layers and
// bind their visibility, definitions, selections,
// and renderers to scope properties
};
Option 2: Fill the Gaps
Pull requests welcome!

<esri-map id="floorPlan" center="map.center" zoom="map.zoom">


<esri-feature-layer title=“Floor Plan Lines" url="..."
visible="lines.show"></esri-feature-layer>
<esri-feature-layer title=“Spaces" url="..."
definition-query="spaces.definitionQuery"
selection-query="spaces.selectionQuery"
renderer="spaces.renderer"
update-end="spacesUpdated"></esri-feature-layer>
<div esri-legend target-id="legend"></div>
</esri-map>
Option 3: Roll Your Own

<floor-plan-map id="floorPlanMap"
floor-id="spaces.floorId" Definition Query
type="spaces.occupancy" Renderer
show-lines="lines.show"> Visibility
<div esri-legend target-id="legend"></div>
</floor-plan-map>
Demo: Parcel Map

http://tomwayson.github.io/angular-parcel-map/
Parcel Map: Directive API

<parcel-map id="map" parcel-id="{{parcel.id}}"


selection-complete="onParcelSelected"></parcel-map>

angular.module('app').controller('MyController', function($scope) {
$scope.parcel = {
id: '1919377002'
};
$scope.onParcelSelected = function(e) {
$scope.selectedParcel = e.features[0];
};
});
<esri-map /> Directive: Attribute Binding

// isoloate scope // in controller:


scope: { require(['esri/map'], function(Map) {
// two-way attribute binding var map = new Map($attrs.id, {
center: '=?', center: [$scope.center.lng, $scope.center.lat],
zoom: '=?', zoom: $scope.zoom,
// one-way attribute binding basemap: $scope.basemap
basemap: '@', }); ...
// function binding for events $scope.$watch('basemap', function(nVal, oVal)
{
load: '&'
map.setBasemap(nVal);
}, ...
});
});
<esri-map /> Directive: Event Binding

// isoloate scope // in controller:


scope: { require(['esri/map'], function(Map) {
// two-way attribute binding ...
center: '=?', map.on('load', function() {
zoom: '=?', $scope.$apply(function() {
// one-way attribute binding $scope.load()(map);
basemap: '@', });
// function binding for events });
load: '&' });
}, ...
<parcel-map /> Directive: Attribute Binding

// isoloate scope // in controller:


scope: { require(['esri/map','esri/layers/FeatureLayer', …],
// one-way attribute binding function(Map, FeatureLayer, …) {
parcelId: '@', var map = new Map($attrs.id);
// function binding for events var parcels = new FeaturLayer('http://…', {…});
selectionComplete: '&' // add basemap and feature layer to map, etc
}, ...
$scope.$watch('parcelId', function(nVal, oVal) {
// select feature by parcel id and zoom to it
});
});
<parcel-map /> Directive: Event Binding

// isoloate scope // in controller:


scope: { require(['esri/map','esri/layers/FeatureLayer', …],
// one-way attribute binding function(Map, FeatureLayer, …) {
parcelId: '@', ...
// function binding for events parcels.on('selection-complete', function(feat) {
selectionComplete: '&' $scope.$apply(function() {
}, ... $scope.selectionComplete()(e);
});
});
See the Source });
Rate This Session
www.esri.com/RateMyDevSummitSession

You might also like