ArcGIS API for JavaScript: Building Apps with Angular

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi I'm Andy Gunn and I'm here with my colleague Allison Davis and we have a fun packed text session for you today on building apps for angular with the ArcGIS API for JavaScript we have a full schedule of topics for you we're going to apparently merrily be looking at patterns related to the angular CLI we're going to cover two different ways to load the ArcGIS API for JavaScript modules within your application the first one is going to be as reloader and the second one that i'm going to close out the session today with will be working with wet pack we'll look at major topics related to async patterns the cdk for angular will talk about using services and routing and perhaps most importantly we'll talk a little bit about using state management to manage your app within a larger angular application just a few housekeeping items before we get started this session is about angular 6 plus and more specifically it's about angular 9 the repo that this session is based on at github comm slash ESRI angular CLI ESRI map we typically only address issues based on the latest production version of angular which in this case at this stage is angular 9 the good news is if you're using angular 8 that it's similar enough the angular 9 that will also be able to address those questions effectively also to keep in mind that this is for the version for the our chess API for JavaScript if you're using the version 3 then you'll need to upgrade to version 4 before using these patterns the patterns that we're showing in the text session today will not work with version 3 and last but not least if you're using angularjs also known as angular version 1 again you'll also have to upgrade before using the patterns that we show here this will be good information for you to have in your back pocket but the information will not be usable the patterns will not be repeatable within angularjs and before we get started I have a few items to orient you to where we are so that you can not only follow along but also get started if you're just new to angular or new to our JavaScript API the primary repo for these sessions is shown here and I'll pause so that you can freeze on that and look it up and set your browser to that we recommend digging through the repo so that you can follow along during this tech session as well as having access to it as a resource after the tech session so let's take a quick look at that repo there's two folders as well as a readme that talks about how to get started these slides are in the docs folder the real meat of the repo all of the sample and example applications that we're showing today are available in the sample apps folder everything that we're doing today all the source code is available there and it's a much deeper dive than what you'll get through the online SDK and again this builds on the angular CLI ESRI map repo all the source code is here for your viewing pleasure if you're new to angular or new to our JavaScript API at developers arcgis.com slash javascript under the guide topic is some very high-level getting started information on installation and configuration so you can get going before you dig into the content of this tech session and lastly I before I hand this over and one to familiarize you with some of the app scaffolding these are just some of the basic patterns inside the repo that we'll be repeating over and over again as important concepts so that you can get started quickly and easily with the ArcGIS API for JavaScript and so let me flip over to Visual Studio code and I am in the app scaffolding repo that's inside the sample apps directory and just wanted to point out a few things in package.json I you can either NPM install ESRI loader or manually add it to your package JSON and these types the ArcGIS J's API types are optional and not required but we do recommend them as a best practice and you can either npm install those or manually add them to your package Jason and another pattern that we recommend is in your CSS or your sass is here where you want is where you want to import your JavaScript API CSS as well as any other CSS related to the mapping component to ensure that the CSS is consistently loaded in a way that looks correct to the end-user during the life cycle of the application and last but not least is you'll see this pattern repeated throughout the next several demos in your main mapping component and almost all of these repos under sample apps do have a mapping component to modularize that functionality to see how the mapping component more easily interplays with the other aspects of pairing components or other components that you have within your application and you're also going to see this pattern the low importing the load modules method as well as just the last note that I'm going to make is you'll see us referring to the types namespace just as a simple variable makes our code look cleaner and that's all we're doing is just making it look look a little bit more appealing since you have to look at it all the time versus just using the standard namespace so with that I'll turn it back over to Allison Allison take it away all righty so I'm going to talk in a little bit more detail about as reloader ESRI Lauder is a small open source library that allows you to lazily load arcgis modules which are an AMD format into any JavaScript application no matter what framework or tooling you're using so you can lazy loading is set up by default if for some reason you don't want to use the lazy loading in your application you can also use a static script tag so check up as reloader Docs for more information on how to set that up ESRI loader works with the JavaScript API either 3x or 4x all of our demos though are going to be using the 4x JavaScript API and the nice thing is even if you're not writing angular applications ESRI loader works with any loader bundler framework config and it also it does integrate really nicely with the angular CLI right out of the box so you don't have to worry too much about trying to customize anything to get this working so here's an example of what this would look like in code so we're just importing that load modules from ESRI loader and that dynamically injects a script tag onto the page and then you can use either a promise paste pattern or you can use async await so if you're using a promise you call load modules and you pass an array of the modules that you're using in your application and then once that has resolved then any ArcGIS JavaScript code that you're writing would go inside of that function call there you could also if you're using async await then you can just set up an async function and then await that load modules call with that same array of you're using so either those patterns works super well and another tool available for you to use in your applications as types for our GIS - jsapi so typescript is as you probably know a typed superset of JavaScript that compiles to plain JavaScript and there's a lot of benefits that typescript brings to the table into your code using types means cleaner code and fewer errors we also get a tell isense in our IDE it makes working with for example complicated API responses or large data objects a lot simpler to kind of define the shape of the data that we're working with in our application it really helps your JavaScript scale really well so typescript is used by angular as a primary language for app development and ESRI in turn provides type definitions for the ArcGIS API for JavaScript which you can install using NPM or your package manager and so it really really helps when you're working with the jsapi to have access to those immediately in your code so I'm not going to go into too much detail there because typescript configuration and working with typescript could be a whole nother session almost but if you want to check out additional resources we have ESRI has a type script setup guide linked below and angular also has a lot of really great resources around digging into the typescript configuration in your applications we also have a sample app that shows kind of the base configuration for working with the ArcGIS j/s types in an angular CLI app that's linked in the title of this slide so check that out next I'm going to talk a little bit about async operations in your angular applications and there are certainly other patterns for managing async and out of sequence operations but these are three big ones that you'll see a lot the first is promises then we have custom events in angular and finally rxjs and observables so first we're going to take a look at promises demo application I'm gonna pop over here I'm running this demo locally and you can access all of this code in the github repo if you'd like to follow along or you can run it on your own machine later so here we have our demo app we have a select menu and then a map here and we can select a world wonder and then our map will pan to that landmark and as you see each time we select a different value in that select menu first we see a little panning message that panning is in process and then we see a done message flash on the screen and you also might have noticed that the Select menu is disabled while the panning is taking place I'll show that again so I'm gonna show you a little bit of what's going on in the code so inside of our angular app we have a couple of different components that we're working with we have a parent dashboard component and then we have a child ESRI map component that we're using and so here in our dashboard parent let's scroll down just a little bit we're using view child so that we have an instance of that ESRI map component here and we're setting an instance of that to the variable map and then a little bit further below you see this selected wonder function now in our dashboard template here's our select in HTML and we're just on the input event we're just calling that selected wonder function in our component here and that in turn so when a change or an input value occurs inside our select menu then the select wonder function is run and that in turn calls this dot map type and map so it's accessing that child component and then call in the pan map function pan map if we pop over to our ESRI map component actually returns a promise and so when that promise resolves it's zooming to a level of the map the set timeout is occurring just so that we can see a more exaggerated result when we run this demo application without the set timeouts the actual function calls go way quicker so it's harder to see when you're playing around with this demo so that's why that's there so back in dashboard so selected wonder is called first the panel is disabled so that select is just completely disabled we call pan map and then once we have our promise resolved then we call enable panel and then we see that feedback message if done and then we can select another world wonder and do another pan call and again you'll see another set timeout here again that's just to make the demo a little bit more legible as were stepping through and playing around with this code so next we're going to take a look at a pretty similar demo but using angular custom event and the event emitter to manage our async operations so let's pop over to a browser again so we see a similar demo we see the same select we select a world wonder our map is panning and then again we see a done call and then our menu is again re-enabled so the functionality here is quite similar to our last demo but let's take a look at the code and we'll look at some key differences there so inside of our application code we again have a parent dashboard and then a child as remac component we're again using view child to have a reference to an instance of that child component in our code with the variable map and then if we scroll down a little bit we see again our selected wonder function but what's going on under the hood is a little bit different so first things first let's take a look at our dashboard components template and again we've got that event binding to the Dom event of input and that's what's calling that selected wonder function now if we go over to every map we see that same pan map function but we also have an instance of an event emitter and so what we're doing here is creating a custom event emitter called wander mapped and what's happening is we've got the same pan map functionality we're zooming in and going to our coordinates and then once our promise is resolved then we're calling this dot emit and so that is a method that's on this instance of the event emitter so we're emitting this event and then what happens is actually the child component emits this event to the parent so if we go back to our dashboard template and here is our instance of the child component we see that we have actually bound to this wonder mapped event and then we're calling an able panel so back in our dashboard component this is kind of the order of things so the input from our dashboard component changes selected wonder is called first the pant the panel is disabled then we're calling this dot map so that's the instance of our child component dot pen map pan map in our child component actually emits that custom event and then when the parent receives that event that's emitted from a child it calls the enable panel function which is defined down here and that's what is rien a Boleyn our select and we also see that that feedback message I've done and again we've just got the set timeout functions kind of sprinkled throughout the code just to make the order of operations a little clearer and a little easier to see as we're stepping through this demo in the browser so our final a think pattern that we're going to be taking a look at is observables and rxjs so observables are used heavily within angular for lots of different common async operations HTTP requests reactive forms routing and actually under the hood angular custom events so the event emitters that we were just looking at in our last demo that's actually an extension of the rxjs subject so if you want to learn more about observables and their usage within the angular framework you can check out the angular Doc's linked here they have a lot of really great information about kind of how and why they're using that paradigm rxjs is a library for reactive programming that provides an inflammation and implementation of observables and utility functions for working with observables and creating them rxjs is necessary in order to use observables in JavaScript until it becomes part of the language and browsers support it whatever that might be in the meantime you have to use rxjs in order to use this programming paradigm and so observables in a little bit more detail so they provide support for passing messages between publishers and subscribers in application code and so observables are declarative meaning you define a function that publishes values but that function isn't actually executed unless you have a consumer subscribing to it and then once it's subscribed then receives notifications until one of two things happens either the function completes and therefore ends the process or if the consumer unsubscribes then that also would end the stream so you declare the function but it's only actually running and their own the consumer is only actually receiving values if subscribed and observables can deliver multiple values of any type and the really nice thing about observables is that the observable itself handles setup and teardown so all your application code needs to do is to subscribe in order to consume values and then whenever it's done unsubscribe and that doesn't matter whether the the stream of data being received is keystrokes as a user is typing into an input box response from an HTTP request or an interval timer the the process looks exactly the same and so basically as an example we can see here in the demo we're about to look at we have a subscription to find here we subscribe to these value changes in this case these are the value changes a subscribes orbble that is created with morn using reactive forms we subscribe to that and then whenever a change takes place we take that value and then we can write code to handle that value however we like it's really important when you're working with subscriptions in your components though in ng ondestroy in your component life cycle to unsubscribe to any subscriptions that you may have done earlier in your component lifecycle and that's really important for avoiding memo memory leaks and just maximizing performance in your application so we're going to take a look at the same demo looking at the world wonders but this time we're going to be using observables in a couple of different ways both within a service and so with how we're receiving data and then also through the reactive forms module that angular provides to us so the functionality again is pretty similar you'll see we select Great Wall of China we have our panning message the panning and animation takes place and then once the pan operation is complete and we zoom in you'll see that dumb message and then once again the input is re enabled now the other thing that we have here is thanks to the reactive forms module we can actually log out some information about our form and what's happening to it at different points in the application so for example we can say that so far the form has not been touched since this component has been reinitialized the form value is currently set to zero because that's the first value in our list of inputs here if we change it to Petra you see our form value changes to one great and then you'll also notice that when that form is disabled form valid is actually set to false and then when it actually has a value once everything is renamed you see that it's set back to true so let's take a look at the code and see what's actually going on under the hood so in this demo the first thing that we're going to be doing is creating a service that components in our application I can actually subscribe to within their their own code so andis gonna talk a little bit more about services in detail but for now we're just importing subjects from rxjs and we're creating a couple of different subjects pan request and then a pan complete and then here you see that we're also setting our list of wonder landmarks here and then in the pan to wonder function we have the ordinance that are getting passed in we're setting those and then calling the next function within that that subject so what this looks like if we go over to our control panel you see in here we have a couple of subscriptions in the ng on an it function so that's in our component life cycle when our component initializes and the first thing that we're doing is we're subscribing to this pan complete observable that's set by our map service and then once when any changes come through from that subscription then we're calling the enable panel function and you'll see up above as in our other examples that just means that were re enabling that form and we're setting that feedback message to done so that flashes once that pan is complete and then over in our map component let's go over here so what we're doing here is we're actually we have our map service inside of our constructor here and then inside of this pan map function we're going to our specified coordinates and then just as before were calling or setting that zoom level to 18 and then on complete we're calling this map service pan to wonder complete so letting the service know that that pan logic is completed and then we also have a subscription here so that the the pan request is subscribed to and then whenever changes come through then we're calling this dot pan map and handing off the the coordinates to that the other thing that we're doing in the control panel component is that we're all so we're using form control which is from the angular reactive forms module to that we can get some of the benefits of that reactive form module so if we pop over here you'll see that we set wonder form to a new instance of form control and here in the constructor you can pass in an initial value if you like and there are also some options that you can check out in the angular Doc's that you can also use for right now we're just setting up a new empty form control and then over in our control panel template you'll see here we're setting this select the form control input to equal wonder form which is the name of the form control that we just initialized the rest of this code is the same and then here down below these are where we're logging out that form information that we can get from our form control so all of these are properties of the form control so if the user has touched the control if the value the value of the form is valid and then the value itself so not just what's appearing here in the element but the actual value attribute we can log all of those out that's really handy for debugging and also we can do a lot of really cool things with form validation when we're using a reactive forms and custom validators so back in our control component down here so we have our wonder form subscription and value changes is something that's provided to us by the reactive form module and so we can actually subscribe to any value changes in the form and then if any changes take place in that control then we actually have this value wonder and then we can do something with that value and so here we're saying that if at any time the value changes we want to disable that panel we call our pan to wonder function and then because we're subscribed to that pan complete observable that's when an able panel is called and taken care of here and then as you can see in the ng ondestroy part of the component lifecycle we're unsubscribing from both of those rxjs also provides a lot of great operators for doing things like combining observables only taking the first valid emitted value from an observable and then automatically unsubscribing there are a lot of really cool ways that you can work with streams of data and observables in your applications so those are the three different async patterns that we're going to cover and as I was saying earlier the the links to all of these demos are available in the slide titles there's a demo for each pattern so check those out on our github repo you can pull those down and run locally and play around with those and then we've also tried to link to different points in the angular documentation that talks a little bit more about where these patterns crop up when you're using this framework so next I want to talk a little bit about the angular component developer kit or cdk and this is a library authored by the angular team and this is a really great resource if you're working with custom components and UI and what it does is that it implements common interaction patterns and components some of which are quite complicated things like portals or like different kinds of dropdowns different kinds of accessibility behavior a lot of the they're really complicated and quite technical pieces of UI component development that can get really challenging and really bogged down developers if you're trying to create things from scratch and the great thing about the developer kit is that it's also totally unabated about how you present these components basically everything is unstyled these things really really lend themselves well to working as a foundation and then having you build your actual component design on top of that and styling it yourself an angular material which you may have worked with before which is the material design library of components for angular is actually built on top of the CD k so the CD K is kind of the basic foundation unstyled and then angular material is built on top of that so for example would pop over to the angular material docks we have things like portals and stuff like that we're scrolling and then styled components within angular material are actually built on top of these foundations so everything is very high-quality everything is maintained by teams that are part of the angular and Google teams so the quality is very very high and it's a really great resource for getting complicated components and pieces of UI going in your applications so this is where you'll find documentation on the cdk here and we're going to look at a simple demo where we're bringing in the data table component which the documentation you'll find right here and this is an unattainable version of that into an application demo building off of the demos we've been doing with our async operations back here and so the other nice thing about using the cdk components is you have access to accessibility and responsiveness they work right outside of the box so if we jump to our demo and I resize the browser you'll see that my table is actually automatically shrinking as the size of the window changes and that's handled by the cdk I didn't make any changes in my component to account for that so that's really really nice to not have to deal with that and then also developers have full control over the functionalities so it's really easy to create your own custom Styles things like sorting and pagination you really can add that on top um one kind of note of caution you know if you're looking for something that's a little bit more ready to go out of the box I would recommend working with angular material and not the CD came this is definitely designed more for developers that don't want to implement kind of the the base behavior but at the same time they want to have a lot of say over how they style things how their UI interactions work so building your own sorting pagination etc those features have to be added on top the other nice thing is that the template of this table and our data source they exist completely independently of each other and I'll show you how that works in code in just a second so going back to our demo here and all that's happening here we have a table and we're exciting an ID for each wonder of the world we have a name and our coordinates here and if I click on one of these rows you'll see that same pan and zooming functionality that's occurring has been occurring in our other demos and then there we are so next I'm gonna crack open our editor here and we can talk about a little bit about what's going on under the hood so inside of its demo the first thing I just want to call attention to is the table component that we've built so we're bringing in a couple of things the data source this is from the CD Kay we're going to use that to create an instance of a data source to connect to our table we're bringing in the ESRI map service that's pretty similar to what we constructed in the last demo and then we're also bringing in behavior subject and observable from rxjs and if we scroll down a little bit and the first thing that we're doing is just setting up a wonder interface to create the shape of our data if you will so we're setting a property of ID which is a number name which is a string and then coordinate which is an array of numbers and then for right now we're just hard coding our data set here has wandered data and as you can see each object in this array follows that wonder interface and then a little bit further down so inside of our table component we are injecting an instance of map service and then we're creating our reference to data source so we we create the the class test data source a little bit further below and that's where we're actually setting what data we're going to be using in the table and then we also have this handle click function which is actually handling a logic of what happens when a table row gets clicked on and then below here we have the the datasource class so this is returning a behavior subject or data property rather is an instance of behavior subject which in turn is an array of wonders we're using that wonder interface up above and we're just passing as an argument that constant wonder data that we defined up above for the purposes of this demo and then connect so this gets called under the hood actually by our cdk table and we're just returning this dot data so this is something that the data table can can hook on to and subscribe to and then in our template the first thing that we do here inside of our table and you'll see these directives all over the place this is how the cdk actually defines you know tables table cells table rows as part of the cdk table using these directives and then we actually we have an input of data source that we're setting to the data source that we defined in our component and then inside of each of these instances of ng container we're setting a header cell and we're also setting the actual column definition so each of these we're hooking into a different property of an instance of wonder so here we have wondered ID wonder name and then here we're manipulating that a little bit so in our data set we just had an array of coordinates and here we're actually displaying those wonder coordinates at index zero and then at index one to display that X&Y coordinates and you'll notice here we're setting these header cells and the the names will display on our data and you can also there's a similar directive cdk footer cell where you can do the same thing and then here we have our header row and that's where if we pop back to our table we have an array of displayed columns so we're displaying each of the columns now you can change these and hide or show columns so if you have multiple instances of a table that could be useful but for right now we're just doing all of our displayed columns which are all the columns we've defined and then here we actually have those row definitions and then we're iterating over each of those now in the table row is where you can actually do things like add eventlistener so we have added a click handler where we're calling that handle click function you can also do some really cool things with conditional styling that's based on the data in your table for example if we wanted to highlight all of our world wonders that were in a certain range of coordinates we could do that if we had additional data field you know say the continent where each world Wonder was located we could do some conditional styling in that way so it's really nice because even though the table and the data are existing independently of one another we can also rely on that template to do some really cool conditionals with the data that we're bringing in so that handle click function is over here in our table and we're just calling that same pan to wonder function from our map service and just passing that the array of coordinates from the roam so that is a relatively quick introduction to the angular cdk and now I'm gonna pass things back to Andy and he's going to talk a little bit more about using services as well as state management in angular applications thanks Alison now I'm going to talk about angular state management and there's many different aspects to state within an angular application including the application state the component state the shared state the router state but really what we're focused on here and the examples I'm going to be showing is the state of the map component and there's many many different choices for how you go about doing this and there's no wrong answers it depends on your requirements it depends on your skill sets and it depends on the capabilities of these different libraries such as rxjs rxjs plus redux ng rx NGS X and angular redux and the list goes on I'm going to be showing just two examples I'm going to be showing a simple store it's using plain old rxjs as well as an NG rx datastore which is a lot more scalable solution so the first sample that I want to show again is just very simple map state and I just need to maintain this state between routes and I'm going to use a service to do this built on rxjs so here's my application and it consists of three different components I have the header component with a viewport that's empty right now I have my mapping component which is here and in another tab I just have a different route that shows a different component just to show the example of navigating away and coming back and the idea behind this is a couple of things one for to set the stage for my next demo is to show you when the user navigates away from this notice the island is on the left side of the map I'm going to navigate away and then I'm going to come back the map reconstitutes to its default and that's okay for the purposes of this application right here what this application is really designed to do is when the user clicks on the map like this I want to be able to preserve those points when the user comes back to the mapping component so I'm going to navigate away and then I'm going to come back and when my map reconstitutes the points are still there and I also want to share this data in the header component I want to share these latitude longitude so that as soon as the user clicks that viewport is automatically updated with those points so there's a few things going on related to maintaining state in this application so let's go ahead and take a look at the code the key part behind this is using rxjs observables and behavior subjects in my service and behind the scenes is just a very generic map store that's as decoupled as possible when I say generic it's completely decoupled from the service in as many ways as possible so that it has complete flexibility with how the service or other other services access it so in this case it just ups three things it lets me get the value from the behavior subject it lets me get the state as an observable and it also lets me set the state using a base you're subject and that's it that is all this data store does and it's just storing an array of lat/long so it's very simple so let's go ahead and look at the service that's accessing the store and here I have my map store service and it lets me do two things it lets me get the points so I can retrieve the set of latitude longitude that are stored within that array and it lets me add an individual point so that's it that's all the service does in this case I want to point out one more thing is that the map store does need an initial value so in the super method of the constructor you'll notice I'm just passing an empty array and there's multiple purposes for that so let's go take a look at my map component and see how we use this service so in the ng on an it when the map view is initialize so this is when I navigate away and come back this is not for when the application is restarted this is just during a single user session when the map is ready I'm going to subscribe to the service I'm going to retrieve those points that array in this case it's ESRI graphics that I'm storing and if there are any available so remember I just passed an empty array and the super of my service if the empty array of turn returns I'm not going to do anything when the map first loads if there is values in the array I'm going to go ahead and add those to a graphics layer in my map and then I'm going to simply unsubscribe and I'm done that's all I need to do is when the user navigates away comes back if there's points of graphics that need to be reacted to the map I do that and then I can unsubscribe and I'm done in terms of the workflow where the user is adding points on a click with each click I create a new graphic I add those graphics to the graphics layer and within my service I'm using the add point method to simply add that graphic to my store that's it so let's take a look at the header component the header components a little bit different it's subscribing to the service continuously so that if the user does click on the map I can populate that viewport so in this case I'm doing something a little bit different now I'm still I'm still subscribing to my service through the gets get points method but I'm also detaching change detection now this is something that typically you just want to use the default settings and update the UI at about 16 to 17 milliseconds in this case the user isn't clicking on the map very often and I only want to update the user interface when the user clicks on the map so whenever there is a next value in my service I go ahead and process the latitude longitude I pass it to an observable and then I force change detection on the UI to update the user interface so let's take a look at the HTML for this header component so I'm using a cdk virtual scroll viewport I'm simply implementing the cdk virtual four to iterate on my P message observable and what I do is anytime there's an update I'm going to iterate through that array in P message and display it in the header and that's it that is my example of a very simple store it's just storing an array of latitude longitude when the user navigates away from my mapping component and comes back that data is restored and I'm sharing that data through a service into another component now let's take a look at a much more scalable approach to maintaining application state and this example uses an ng rx data store and a picture is worth a thousand words let's just go ahead and take a look at the application this is very similar to the simple map State application except it addresses one specific item that I pointed out that is a deficiency in the simple map state app here I want to be able to save the state of the map it's zoom level and center when the user moves away from the map navigates to another component and comes back so I'll show you here that I've changed the zoom level and center I can go on a different route navigate back to my map and it's reconstituted in exactly the same place now just to be clear this is during the user session this this is not storing offline State in the sense that I could close the browser tab and come back and expect to have it restored this is just within a single session that I want to preserve the state of the map so let's take a look at the code so here I am inside the data store folder the repo and we're gonna take a look at how I built this state it's all stored in these all the different pieces of it are stored within the state subfolder let's first take a look at indexed es which is essentially loads all the different aspects of my data store and here I have two different aspects I have a create selector which lets me select the map state as you can see here and I also have a reducer which lets me create something actionable against my data store so let's take a look at the reducers there's a couple different aspects to this is I have a reducer here to set the map state that's where I'm gonna change the data store and literally when I run the set map state method it's going to change that value within the data store it's just gonna add it directly to the data store and I also have a select map state not to be confused with set this is select that's going to either return an initial state if my store hasn't been set up before or the current state of the map so let's take a look at the initial state I've created an entity adapter that defines the default values for the state within my application and I have a zoom level of 12 here and I have a serialized string for the object that represents the map views Center so I have one model and that's my map settings it simply contains zoom as a number and Center as a string as I mentioned before I'm doing that for serialization purposes I can set it as a string and deserialize it as Jason to use it directly within my mapping component I also have one action the set map state I use the create action method and as you can see this is part of ng RX data store as I've set in my imports here and when I when I want to set the map state it's very simple I set a props property I set props based on a map property and in it is just my map settings object and that's it so let's take a look at how that works within the mapping component and I'll just start at the top and work my way down is this is all used internally within the component I don't have any connection to the user interface here just to make that clear this is just updating the mapping component and how the map works when it's reconstituted when the user navigates away and then comes back so at the heart of this is a map state observable variable and a static map state variable which is just a snapshot of my observable so I'll show you how that works in my constructor I'm importing my store and I set the observable up based on a store pipe and what that pipes doing is using my select map selector I know that's a mouthful but that pipes calling the select map selector and essentially injecting that into my map state observable so an ng on Annette I go ahead and subscribe to that observable which is my store and every time my store is updated through next I create a new snapshot using static map state so every time my store is updated I want to capture that information in in my local store I'm sorry in the application store so let's go down to map view when the application is first loaded I'm going to use that select map state to set the center and zoom so to do that as I mentioned before I have to basically deserialize this so I json.parse my string and set the center property on my map view I take the static map State zoom and set my map view zoom property so now when my map loads it's going to set up the store it's going to subscribe to the observable if there's any information in it it's either going to grab the initial state or the current state and it's going to set that on my map view and so when the map view is reloaded all of that information will be available and it'll be returned to the previous state that the user left it so the way that I'm updating the state when the map navigates around is I'm setting a watcher on the extent property so once the map is loaded map view dot when I set this watcher and within that I have a deep bounce a function that runs a deep mount sir so as the user navigates the extent the extent property is fired a lot there is a lot of a lot of extent changes that come with that and we want to settle that down a bit in the D bouncer and try and and minimize the number of times that we're calling store dot dispatch on that to set the map state so we run this through the D bouncer which is calming things down there's a lot of events firing I create a new map settings object and I use the store dispatch function to set the map state that is the only way that I can change the state within my store that's the only way that I can do it and that's it it's a very simple but very scalable example of how to maintain a simple map state on the map as the user navigates around and to return to that state when the user navigates away and then comes back so for the next section I'll talk about using webpack with the ArcGIS API for JavaScript all right so let's talk about angular and the ArcGIS web pack plugin all the code in this section is available in the angular CLI ESRI repo under the ArcGIS web pack angular branch so if you go to the repo github.com / ESRI and you select the ArcGIS webpack angular branch all the code is here including a readme that provides some basic instructions on how to get started with this some key things to know this only works with angular 8 and angular 9 and it only works with the ArcGIS API for JavaScript version 4.7 plus only and you will have to configure web pack using builders you can't eject web pack anymore in the latest versions of angular and builders and provide delegate functions for doing things like linting and testing and of course building and the one that I'm using for this example is a custom library that helps with that you can build your own and I don't recommend it so I use angular builders custom web pack library so if we go ahead and open that up and just take a quick look the latest version was just published a few days ago for for angular 9 and it's available on NPM now once you've installed this there are some configuration things that you need to do in order to get it to work right but it's really straightforward in your angular JSON under the build task you're going to change the Builder path to represent angular builders custom web pack and set that to browser and you're also going to specify a custom web pack config file which we'll talk about next and you also want to set up your new path for serving just something to be aware of that if you don't set those things aren't going to work quite right you will create a web pack config file in the root of your application or wherever you want to put it and this is where you import the ArcGIS web pack plug-in you can see here that we're bringing it in through a require statement and then there's just some basic module exports that you need the set I'll call attention to setting FS to empty off the bat that's a good place to start could eliminate some troubleshooting and and some compile time errors when you go to initially launch your application so that's just something to pay attention to that might save you some time and head-scratching later once it's installed and you go ahead and build your application everything on the inside of the application is going to look different than what we've talked about before when you're using ESRI loader now if you're using the web pack plug-in you can use this pattern just like this so standard yes and imports are the way to go and the word the day when you're using the web pack plugin pretty cool right just simply say import map from the path name to the module and boom you are done so in ng on an it in this particular application it's going to look just like you would expect it to except now you're newing up a class name exactly as you would expect it in a plain old JavaScript application without the need to use as reloader without the need to import your own required statements now all that's being handled behind the scenes for you it's still there but within your application you can use standard import statements just a word if you're working with secure services and you start seeing worker global scope errors something the effect of what you see here then there's a couple additional steps that you need to take I've provided a handy link here so that you can look at this information yourself is you want to import as reconfig just like you're at the top of your application and then an ng on an it before you run your application code you're going to copy and paste this block of code in there to handle how workers are used within the JavaScript API of course you want to change this to the latest version which is currently 4.14 we hope this is just a temporary solution in the long term we are aiming for pure ESM compliance but for now if you run into these errors that is the way to go to solve them of course if you have any other issues you any other problems feel free to open an issue on the angular CLI ESRI map repo and we'll do our best to take care of you and that's it that brings us to the end of our presentation we covered a ton of things related to using the ArcGIS API for JavaScript and angular from ESRI loader to async and cdks and maintaining state and a lot of other cool things we talked about we hope you found this super useful we've provided a bunch of additional resource links at the back of the the reveal deck I guess that's going to be converted into a PDF for you that you can click through to get access to these the presentation getup repo references to the guide topics ESRI loader ArcGIS web pack plug-in and much much more those resources are just available right here for you and on behalf of Allison and myself we thank you for tuning in for the session we hope that this helps you get started quickly and as always feel free to reach out on github.com slash the issues there if you have additional questions thank you very much
Info
Channel: Esri Events
Views: 4,214
Rating: 4.7777777 out of 5
Keywords: Esri, ArcGIS, GIS, Esri Events, Geographic Information System
Id: ea4D-qGU0_0
Channel Id: undefined
Length: 64min 26sec (3866 seconds)
Published: Wed Apr 22 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.