Declarative Mapping Applications with AngularJS › library › userconf › devsummit... ·...

Preview:

Citation preview

Dave Bouwman - @dbouwmanTom Wayson - @TomWayson

Declarative Mapping Applications with AngularJS

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 FrameworkFriday 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" />

<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>

25 types of layers10 renderers

9 types of symbols100s of events

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

angular-esri-mapesri

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

Regional View of Sites

Floor Plan Map

Site Map

Real World App: Facilities Management Application

Map Legend

RendererLayer VisibilityDefinition Query

Layer Selection

Get Layer Features

Feature Layers

Real World App: Gap Analysis

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>

</esri-map>$scope.mapLoaded = function(map) {

// get references to the feature layers and

// bind their visibility, definitions, selections,

// and renderers to scope properties

};

Option 2: Fill the Gaps

<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>

Pull requests welcome!

Option 3: Roll Your Own

<floor-plan-map id="floorPlanMap"

floor-id="spaces.floorId"

type="spaces.occupancy"

show-lines="lines.show">

<div esri-legend target-id="legend"></div>

</floor-plan-map>

Definition QueryRendererVisibility

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

scope: {

// two-way attribute binding

center: '=?',

zoom: '=?',

// one-way attribute binding

basemap: '@',

// function binding for events

load: '&'

}, ...

// in controller:

require(['esri/map'], function(Map) {

var map = new Map($attrs.id, {

center: [$scope.center.lng, $scope.center.lat],

zoom: $scope.zoom,

basemap: $scope.basemap

}); ...$scope.$watch('basemap', function(nVal, oVal)

{

map.setBasemap(nVal);

});

});

<esri-map /> Directive: Event Binding

// isoloate scope

scope: {

// two-way attribute binding

center: '=?',

zoom: '=?',

// one-way attribute binding

basemap: '@',

// function binding for events

load: '&'

}, ...

// in controller:

require(['esri/map'], function(Map) {

...

map.on('load', function() {

$scope.$apply(function() {

$scope.load()(map);

});

});

});

<parcel-map /> Directive: Attribute Binding

// isoloate scope

scope: {

// one-way attribute binding

parcelId: '@',

// function binding for events

selectionComplete: '&'

}, ...

// in controller:

require(['esri/map','esri/layers/FeatureLayer', …],

function(Map, FeatureLayer, …) {

var map = new Map($attrs.id);

var parcels = new FeaturLayer('http://…', {…});

// 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

// in controller:

require(['esri/map','esri/layers/FeatureLayer', …],

function(Map, FeatureLayer, …) {

...

parcels.on('selection-complete', function(feat) {

$scope.$apply(function() {

$scope.selectionComplete()(e);

});

});

});

// isoloate scope

scope: {

// one-way attribute binding

parcelId: '@',

// function binding for events

selectionComplete: '&'

}, ...

See the Source

Rate This Sessionwww.esri.com/RateMyDevSummitSession