ArcGIS API for JavaScript Programming Patterns and API ... · Write apps in ES6 or TypeScript...
Transcript of ArcGIS API for JavaScript Programming Patterns and API ... · Write apps in ES6 or TypeScript...
ArcGIS API for JavaScriptProgramming Patternsand API FundamentalsJulian Kissling | Rene Rubalcava
slides: https://git.io/Je0yr
1 / 55
What do I get with the 4x JSAPI?Simpli�ed and consistent APIWrite apps in ES6 or TypeScriptModern browser support (IE11+)Supported in 30+ locales
2 / 55
What are my options?Needs?Resources?Time?Customizations?
3 / 55
Why start from scratch?App startersWidgets
4 / 55
Widgets!
We'll look at a few ~30 Widgets out of the boxWidgets help make great appsLess code for you to writeDesigned with responsive apps in mind
widgets
5 / 55
Widgets - Expand
IconsGroupMode
Clickable button to open container
6 / 55
Widgets - Use Portal Content
Basemap GallerySearch
7 / 55
Widgets - PopupMenu actionsDock
8 / 55
Widgets - Popup TemplateDe�ne �elds, charts, custom html content
PromisesArcade
Using a function
9 / 55
Widgets - Author popup in online
Layer.fromPortalItemWeb Map or Web Scene
App Demo
10 / 55
Widgets - FeatureDisplay popup template contentHover
11 / 55
Widgets - Architecture
View + View Model
12 / 55
View ModelsCustom ViewUse the view model
Additional Examples
13 / 55
Geocodingconstconst locator locator == newnew LocatorLocator(({{ url url:: url url }}));; locatorlocator..addressToLocationsaddressToLocations(({{ address address:: {{ "singleLine""singleLine":: "380 New York St, Redlands, CA 92373""380 New York St, Redlands, CA 92373" }}
}}));; locatorlocator..locationToAddresslocationToAddress(({{ location location:: point point }}));;
14 / 55
Geocodingconstconst searchVM searchVM == newnew SearchVMSearchVM(());; searchVMsearchVM..searchsearch(("380 New York St, Redlands, CA 92373""380 New York St, Redlands, CA 92373"));; searchVMsearchVM..searchsearch((locationlocation));;
15 / 55
Geocodingconstconst portal portal == newnew PortalPortal((......));; awaitawait portal portal..loadload(());; portalportal..helperServiceshelperServices..geocodegeocode..mapmap((geocoderServicegeocoderService =>=> {{ // objects with details on// objects with details on
// geocode services for your portal// geocode services for your portal }}));;
16 / 55
Widgets - StylingAvailable Themes
17 / 55
Widgets - StylingCSS Extension languageSASSTheme Utility
18 / 55
Map and View
19 / 55
Map and Viewconstconst map map == newnew MapMap(({{ basemap basemap:: "topo""topo" }}));; constconst mView mView == newnew MapViewMapView(({{
map map:: map map,, container container:: "viewDiv""viewDiv" }}));; constconst sView sView == newnew SceneViewSceneView(({{ map map:: map map,, container container:: "viewDiv""viewDiv" }}));;
20 / 55
Basemaps and GroundConvenience Strings
constconst map map == newnew MapMap(({{ /*/* streets, satellite, hybrid, terrain, topo, gray, streets, satellite, hybrid, terrain, topo, gray,
dark‑gray, oceans, national‑geographic, osm, dark‑gray, oceans, national‑geographic, osm, dark‑gray‑vector, gray‑vector, streets‑vector, topo‑vector, dark‑gray‑vector, gray‑vector, streets‑vector, topo‑vector, streets‑night‑vector, streets‑relief‑vector, streets‑navigation‑vector streets‑night‑vector, streets‑relief‑vector, streets‑navigation‑vector */ */ basemap basemap:: "streets""streets" /*/* world‑elevation world‑elevation
*/*/
21 / 55
Basemaps and Groundconstconst map map == newnew MapMap(({{ basemap basemap:: {{ // Layers drawn at the bottom// Layers drawn at the bottom baseLayers baseLayers:: [[ newnew TileLayerTileLayer(({{ url url:: baselayer baselayer }}))
]],, // Layers drawn on top// Layers drawn on top referenceLayers referenceLayers:: [[ newnew TileLayerTileLayer(({{ url url:: refUrl refUrl }})) ]],, }},,
groundground:: {{
22 / 55
Basemap and Ground
23 / 55
Collections
esri/core/Collection
24 / 55
Working with Accessor
Objects are have properties that can be:read and setor read-onlyconstructor argumentswatchable
25 / 55
Accessor - property accesslayerlayer..opacity opacity == 0.50.5;; layerlayer..title title == "My test layer""My test layer";; // setting multiple values// setting multiple values layerlayer..setset(({{ opacity opacity:: 0.50.5,,
title title:: "My test layer""My test layer" }}));; // accessing the value of a deep property// accessing the value of a deep property viewview..getget(("map.basemap.title""map.basemap.title"));; viewview..setset(("map.basemap.title""map.basemap.title",, "new title""new title"));;
26 / 55
Accessor - property watchingmapViewmapView..watchwatch(("scale""scale",, ((newValuenewValue,, oldValue oldValue,, property property,, target target)) =>=> {{ consoleconsole..loglog((`scale changed: `scale changed: ${${newValuenewValue}}`̀));; }}));; mapViewmapView..watchwatch(("map.basemap.title""map.basemap.title",, ((newValuenewValue,, oldValue oldValue,, property property,, target target)) =>=> {{
consoleconsole..loglog((`new basemap title: `new basemap title: ${${newValuenewValue}}`̀));; }}));; mapViewmapView..watchwatch(("ready, stationary""ready, stationary",, ((newValuenewValue,, oldValue oldValue,, property property,, target target)) =>=> {{ consoleconsole..loglog((`property`property ${${propertyproperty}}:: ${${newValuenewValue}}`̀));;
watchUtils
27 / 55
Accessor - autocasting and single constructor // 4.x// 4.x {{ type type:: "simple‑marker""simple‑marker",, style style:: 'square''square',, color color:: 'red''red',, size size:: 1010,,
outline outline:: {{ color color:: 'rgba(255, 255, 255, 0.5)''rgba(255, 255, 255, 0.5)' width width:: 44 }} }}));;
28 / 55
Promises
29 / 55
PromisesAll asynchronous methods return a promise, no more The basic pattern looks like this:
events
layerlayer..queryFeaturesqueryFeatures((queryquery))..thenthen((handleResulthandleResult))..catchcatch((handleErrorhandleError));;
30 / 55
Promises with async/awaitwork with native promises
constconst doQuerydoQuery == asyncasync ((queryquery)) =>=> {{ constconst results results == awaitawait layer layer..queryFeaturesqueryFeatures((queryquery));; constconst transformedResults transformedResults == results results..mapmap((transformDatatransformData));;
returnreturn transformedResults transformedResults;; }}
31 / 55
PromisesLoad resourcesAsychronously initialized Layer, WebMap, WebScene, View
constconst map map == newnew MapMap(({{......}}))
view view == newnew SceneViewSceneView(({{ map map:: map map,, //...//... }}));; viewview..whenwhen(((()) =>=> {{ // the view is ready to go// the view is ready to go }}));;
32 / 55
Promisesviewview..whenwhen(((()) =>=> {{ returnreturn view view..whenLayerViewwhenLayerView((mapmap..findLayerByIdfindLayerById(("awesomeLayer""awesomeLayer"))));; }})) ..thenthen((layerViewlayerView =>=> {{ returnreturn watchUtils watchUtils..whenFalseOncewhenFalseOnce((layerViewlayerView,, "updating""updating"));;
}})) ..thenthen((resultresult =>=> {{ constconst layerView layerView == result result..targettarget;; returnreturn layerView layerView..queryFeaturesqueryFeatures(());; }})) ..thenthen((doSomethingWithFeaturesdoSomethingWithFeatures)) catchcatch((errorHandlererrorHandler));;
API sample
33 / 55
async/awaitconstconst initinit == asyncasync ((doSomethingWithFeaturesdoSomethingWithFeatures)) =>=> {{ awaitawait view view..whenwhen(());; constconst layerView layerView == awaitawait view view..whenLayerViewwhenLayerView((mapmap..findLayerByIdfindLayerById(("awesomeLayer""awesomeLayer"))));; constconst {{ target target asas layerView layerView }} == awaitawait watchUtils watchUtils..whenFalseOncewhenFalseOnce((layerViewlayerView,, "updating""updating"));; constconst features features == awaitawait layerView layerView..queryFeaturesqueryFeatures(());;
doSomethingWithFeaturesdoSomethingWithFeatures((featuresfeatures));; }};; trytry {{ initinit(());; }} catchcatch((errorerror)) {{
34 / 55
Patterns
35 / 55
Interactivity with view eventsUse view events to interact with the view
You can stop the propagation of the event to prevent the default behaviorList of events
viewview..onon(("drag""drag",, eventevent =>=> {{ // user won't be able to drag// user won't be able to drag event event..stopPropagationstopPropagation(());; }}))
36 / 55
Interactivity with view eventsAccess the features on click
viewview..onon(("click""click",, (({{ x x,, y y }})) =>=> {{ constconst screenPoint screenPoint == {{xx,, y y}};; view view..hitTesthitTest((screenPointscreenPoint))
..thenthen((responseresponse =>=> {{ // do something with the result graphic// do something with the result graphic constconst graphic graphic == response response..resultsresults[[00]]..graphicgraphic;; }}));; }}));;
API Sample
37 / 55
goTo() with ViewSets the view to a given target.
Navigate to a geometry/feature/locationAPI Sample
38 / 55
Loadablesbrings better control, and scheduling of loading resources.extension of esri/core/Promisein 3.x, instanciating a layer loads it. in 4.0, it's an explicit callthe views automatically loads the map and its layers
39 / 55
Loadables
WebMap / WebScene need to load:
the portal itemthe layer modulethe layer's item
MapView / SceneView need to load:
the mapthe layers
40 / 55
//In a single page application, get a feature from a FeatureLayer from a WebMap without displaying i//In a single page application, get a feature from a FeatureLayer from a WebMap without displaying i constconst webmap webmap == newnew WebMapWebMap(({{ portalItem portalItem:: {{ id id:: 'affa021c51944b5694132b2d61fe1057''affa021c51944b5694132b2d61fe1057' }} }}));; webmap webmap..loadload(()) ..thenthen(((()) =>=> {{
returnreturn webmap webmap..getLayergetLayer(('myFeatureLayerId''myFeatureLayerId'))..loadload(());; }})) ..thenthen((featureLayerfeatureLayer =>=> {{
41 / 55
Zoom or Scale
Zoom = LOD (Level of Details)Not all LODs are created equal
constconst view view == newnew MapViewMapView(({{ container container:: "viewDiv""viewDiv",, map map:: map map,, center center:: [[‑‑116.5116.5,, 33.8033.80]],,
zoom zoom:: 1414 // what does that really mean?// what does that really mean? }}));;
42 / 55
Zoom is not Scale
Scale is portableScale has meaningWe still snap to closest LOD/zoom
constconst view view == newnew MapViewMapView(({{ container container:: "viewDiv""viewDiv",, map map:: map map,, center center:: [[‑‑116.5116.5,, 33.8033.80]],,
scale scale:: 5000050000 // I know what that means!// I know what that means! }}));;
43 / 55
WebMap is still a Map
Still acts like a regular MapHas some advantages
constconst map map == newnew WebMapWebMap(({{ basemap basemap:: {{ ...... }},, layers layers:: [[ ...... ]] }}));;
44 / 55
WebMap is still a Map
45 / 55
Sublayer to FeatureLayerYou can extract a FeatureLayer from MapImageLayer Sublayersublayer.createFeatureLayer()Can use capabilities not normally available with Sublayer
46 / 55
Sublayer to FeatureLayer
47 / 55
createQuery
When you can do layer.createQuery()query object will already have the layers �lters and layer de�nitions
more consistentUse new Query() when you don't want prede�ned �lters to be applied
48 / 55
createQuery
49 / 55
MapImageLayerIf you want to modify Sublayers, do it after you load the layerDe�ning them upfront overrides the defaults
May not be what you want
50 / 55
MapImageLayer
51 / 55
LayerViews
Renders the LayerWhen is it done though?
hotly debated topic!When can you actually use it!!Behavior different with optimized FeatureLayer
52 / 55
LayerViews
53 / 55
54 / 55
55 / 55