ArcGIS Experience Builder: Building Web Solutions, Advanced Topics

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome everyone to the ArcGIS experience builder session the building web solutions advanced topics my name is David Martinez and I'm a product engineer on the experience builder development team and with me is my colleague e-way MA hello everyone who is also one of our developers on the team as well and with that let's get started so in today's session we're going to go through the following we're going to do a short intro of experience builder and if this is your first session we recommend you checking out our intro session of experienced builder next we'll go into some widget implementation concepts for creating widgets we'll talk about data sources and then we'll go into developing some meses actions then we'll show you some tips on debugging then we'll switch gears I forgot we got to talk about deployment we'll show you how to deploy the app and that's pretty straightforward then we'll switch gears and talk about more UI centric development for widgets and themes so what is experience builder right well experience builder allows you to create unique web experiences using flexible layouts content and widgets to interact with 2d and 3d data some of the benefits include complete control over the layout and design in other words one design doesn't fit all for those who don't need that complete control you can get started with templates that meet your most common workflows and of course since we're developers we need that ability to extend in the event I need to add my own custom workflows now experience builder has an extensible framework and that's why we're doing this session today and we use several technologies and starting to the very bottom we use typescript it's our official language used throughout it throughout the builder react is a library we use for building interfaces and basically any kind of any widgets that are going to develop are basically a react component Redux is a predictable state container that helps manage app state in an app store and we'll go into a little more details about that webpack is used for module bundling we actually use webpack to listen to any updates when you're developing your widgets and then it packages it up and puts it in a distribution folder and of course we use the latest JavaScript Forex API Jim U is a framework that you're going to use to extend experience builder a gym you core provides the interfaces and types to work with widget props message actions data sources etc it also defines several classes that will be used throughout your experiences and a majority of you that are gonna be working with experience but of course you're going to be working with our GS services so we have a package called Jim you rjs it contains classes and methods for working with the API for JavaScript and typically what's going to happen is you're going to use a Jim you map view and a Jim you map view component the Jim u UI package includes UI components to be using your experiences and then the Jim you for builder provides classes for developing the widget setting page and then of course we have Jim you layouts which allows you to do layouts as well so let's talk about widget implementation and let's discuss some of the patterns that you're going to go through now by default experience builder does not load the ArcGIS API for JavaScript when he uploads and we've done this for performance reasons if you need it it loads if you don't have a widget that doesn't it's not going to load so basically there's two options to utilize jsapi modules widgets that depend on the jsapi like a widget that can almost do nothing without the jsapi you're basically are going to declare that Jim you ArcGIS dependency in the widgets manifest JSON and then you're going to import the module you need for example if you did something like import query then you do the require for ESRI tasks support for last query in your widgets tsx widgets that depend on the J's API conditionally for example you could do something without the jsapi you would use import load arcgis api modules and then you can load the jsap API modules dynamically to load the modules now every confirmable widget should provide a setting page to allow the configuration of a widget in some instances if you're building for yourself you might not have a settings configuration page but if you're going to be sharing it we obviously do recommend that it just gives you a better experience however in some configurations it might be easier to modify settings on the widget rather than the Settings panel and in this workflow a widget can support this feature by enabling inline editing so basically what you do is you would declare support inline editing in the widgets manifest.json under the properties object and then in this instance the widget would have it edit toolbar when the widget is launched in builder a good illustration of this is text widget it's implemented this way another way is you can declare an embedded layout in a widgets manifest under the properties object in this case you would use a layout component to ensure users can drag and drop other widgets in out of the widget there are two components exported from the gym you layouts in the layout builder and the layout runtime and then basically in your widget you would need to use a layout component exported from gym you layout slash layout runtime to access the exported the list widget is in perfect example that uses this technique other options to support inline inline editing is to declare context tool extensions in the widgets manifest.json this declared extension will be available in the selection toolbar the image widget is used in this way it adds it by adding a shape and crop tools in the selection tool bar and to support inline editing the widget might have some modules that are only required when the widget is launched in the Builder so in this scenario you would basically place the modules in the Builder - support tsx file and this file should be in the same folder of your widgets tsx the modules in this file will be available in this dot props dot builder support modules dot widget modules so that'll be available once a widget is launched in the Builder so let's go through a couple of demos because what we did is we built this presentation to show you more Kurtz goats code snippets and less sides okay so I'm gonna go ahead and do is I'm going out and exit out my presentation here am I going to visitors to your code here and the first thing I want you to notice is I've added the entire workspace of experience builder here and basically majority of your your interaction and the builder is going to be in the client folder and we have this extensions here folder which is going to house all the extensions for your widgets in your themes so what I want to do is I'm going to go down I'm going to find this coordinate conversion widget here and we're just going to go walk through this so sometimes for instance you might be required to create a widget that may not be available in experience builder it may exist in github or its shared with you or maybe it's available in the jsapi so we're gonna go ahead and import a widget that's in the jsapi and loading an experienced builder so the first thing that we need to do is we need to import the modules that we're going to use in the in the Builder itself so what we're going to do is we're going to just go ahead and walk through the process of uncoming the the code here and we're going to import react module base widget Jim you map view component and then we're going to import the coordinate conversions from the jsapi okay the next thing that we're going to do is we're going to sorry there we're going to uncomment this interface and basically what we're going to do with this interface here is we're going to basically use this to determine when the widgets loaded so basically it's showing you how this illustrates how to analyze the state and set the state so basically we're creating an interface of state widget loaded is gonna be a boolean okay all right so the next thing that we're going to do now is we're going to create or class for our widget here and then basically we're going to use the type for all widget props we're gonna inject our interface for our state we're gonna declare the container for API widget we're gonna use the interface for the concordant widget and then here we're basically going to support either a map viewer or scene view we're gonna declare it an ESRI watch handle here and basically here we're going to set the initialize the initial state here we're gonna load it at false okay and then we're gonna continue on here and next what we're gonna do is we're gonna we're gonna activate some react lifecycle methods now these are out-of-the-box you don't have to do anything to wire these up and you're working in a class component so let's just go ahead and comment these and basically what this is gonna do is this is going to do a unmount for our widget and basically destroy it to make sure that there's no problems there and the next thing we're going to do is on our active view change here we're gonna basically load the widget to create the coordinate conversion widget based upon the map view here so let's uncomment this so basically on the gym you map view we're gonna get this map view declare it - Jimmy map view then we're going to create the API widget through this function here and if it's this dot map view it's gonna return it otherwise apply a coordinate conversion it's going to initialize a cordon conversion here and then we're going to apply that to our view and then we're going to put that in our container okay so the last thing we need to do to to make this wire up is we need to render this and output it for our display here so we're gonna pass this to our render and we're gonna do tech AE if there's no map selected for this coordinate coordinate conversion select a map otherwise style the court and conversion allow the user to do 100% heighten with and then basically allow them to select the widget ID the for the map and then apply the active view change okay all right so let's go ahead and save this so the next thing that we need to do is we need to have a settings because if we go into our widget for instance we go to localhost here and I go into my experience builder I'm go ahead and sign in all right so let's sign into my experience builder here alright so I'm gonna go ahead and create a new experience let's go ahead and just do a point full screen app let's just call this coordinate conversion here because what I want by default we have untitled for the experience name so let's just call this coordinate conversion here let's hit alright so let's go ahead and find our coordinate conversion let's hit drag you're going to notice that it's looking for a setting so you're gonna see this area here you can see it says select map but we can't do anything because we don't have anything embedded for the settings so the next thing that we need to do is we need to go into our settings ESX file okay and basically it's it's the same pattern that you're doing when you're creating a when you're creating a setting UI it's a similar with one exception you notice we went into the settings TSX file so first thing that we're going to do is we're going to go through the same workflow we're going to uncomment and import the modules we need here and then the next thing we're going to do is we're going to define our class that we're going to use to export so this basically says okay we're going to extend the base widget setting we're going to support so here's a supporter types property and this is going to be immutable for data source type web Maps or web scenes and then we're going to get instance of that and pass to the datasource manager and then on maps selected we're gonna pass it in that settings is a prompt and then the last thing that we're gonna do here is we're gonna render that based upon the map view selector that's a component of the map selected and then use that for the widgets ID okay so we're go ahead save I go back into my experience a little let's hit save here and let's just hit refresh and okay so now if I select here perfect there's no error now so this widget is dependent upon a map so let's go ahead and add a map so let's add a map and let's go and select one here let's go add new data and let's just go ahead and select let's just go with this one and now that we have our map selected here next thing we're going to do is we're going to select this one and this is what we developed for the settings we're going to select the map itself coordinate conversion and what we're gonna do is we're gonna preview this in live mode here so now if I scroll into this map you can see there's a coordinate conversion here I can interact with this and I can add a conversion if I wanted to right so simple demo but very powerful because we've used the widget directly from the API so if there's some widget that maybe we haven't developed right like the print widget or something right you can just go and grab that widget directly from the API itself and then load that and so if I go in here I select map it save core I haven't collapsed my or expanded my print widget but here you can use utilize a print widget to get a PDF output of this map frame so very simplistic but very powerful it shows you that the this widget is dependent upon a map and that's what's unique about experience builder right is that these widgets you could select a different map it doesn't have to be bound to this map because every data source can be unique or it could be across the framework is well okay so alright so now that we showed you that a next thing I wanted to show you is in line editing now a little cool trick here if you go to client and you go to distribution which is dist and you go to widgets here here so here's all my widgets that are that are loaded from my extensions but if you look at these two folders we have common and we have ArcGIS okay ArcGIS is our map centric widgets we give you the source code for these widgets so if I go into the text widget here and I go into this is the distributed source so that's JavaScript if I go into runtime here and I go into tools you could see here it has the Jas files but also the tsx files because this is it's distributed code and our source code so if I go into the inline editing here you can see where we declare this extension here and then we get the default messages to pass and then we provide the editing thought CSV icon right and if we go into our manifest.json here you're gonna see within this array here you have this inline editing context tool and it tells you where this you are UI as for this tool which is where we just were right so that's an example of how you would support inline editing from that and if you want you can you can check all that works by looking at not only the text widget but you can also look at the the image will the image would digit as well that has these type of tools so if we're gonna do crop tools it also shows you the how this works and then if we look at the same pattern for the extensions it's basically the same thing here's calling the crop shape they choose the shape and in the crop tool so now let's get back into our presentation alright so okay so next thing we want to do is I want to talk about data source right and at a high level a data source has a schema okay some records and may have a child parent data source in addition every data source has a type okay now the data source basically defines how it accesses the widget it can be data can be from a remote server it can be stored in the app it can be generated by widget and used by another so for instance if I have a widget that imports you allow people to paste a URL for a feature service that we're just going to generate a dynamic data source on the fly data source instances and statuses are also inject into the widget so you can use those that widget can use the data source and then of course a widget can have more than one data source so when we look at a data source it basically has interfaces right and the interfaces are defined in the Jimmy core and with so and within that package we have common methods and properties so the ID is basically the data source ID okay and the type property is used to check the type of data source it is using every data source must implement the fetch schema method basically it returns a schema this is the schema that defines in the light for instance the remote data service so for example when a user adds a data source and experience builder the data source schema is not saved in the app config it basically will fetch that the get schema method basically is used by the widget to access the data source schema and fields in the data source the get records method is used by the widget to access data in data records in the data source and then we can use the get status to use this property to get the status of the data source so some of these statuses include loading loaded and error and then of course we want the ability to create custom data sources so these can be created by the data source interface by extending abstract data source class now one thing to note about custom data sources is they're basically right today there is no way to configure the custom data source in the Builder so if you have a widget and you want to use a external data source the best practice is to use that external data source and and inside the widget and fetch it directly there's basically no need to wrap it in to the the widget it's self because in the Builder you won't be able to allow you to do that and then the data source is managed by the data source manager so so what are some of the main features for the data source well it has the ability to share data between widgets it also has it provides a pipeline from one from data at parties pipeline from data for data from one widget to another and and you can create data at runtime and I'll show you an example of that and then you can create selected data source in URL to create a state for the URL so if you have a certain data source you can reflect that in the URL and then the ability to change the data source right so we don't want it to break the app if that changes and then what that allows you to do is the data source is reflected throughout our framework or you can do it on individual widgets it's it's totally up to you how you configure that so how do you how does data source use well the data source like I've said before it's defined how your widget access this is that data and the use of a data source is declared in the app config with the property used data sources the config JSON is going to be located in every server app public apps folder and I'll show you that and then this is snippet below you could see here this data source has a couple different properties it has web scene and web Maps and then it gives the item type and label and ID of that data source so rather mean talking about it let's let's go into some examples of some data sources okay so one of the things with experience builder is your application necessarily doesn't have to have a map okay so if I go back into my builder here I'm gonna go ahead and grab this widget called count features it's going to tell me to select the data source and then here I have Texas says okay feature count select data and then I'm basically going to select US breweries and basically we're gonna notice it basically did a query and it basically gave me a future count others there's 3939 records in here and what do you see straight off right off the back there's no map right so what you can do is you could develop widgets that maybe just have a data source but don't have a map maybe it's you know some kind of query and it just shows some data sets data source in a list but there's no map dependency and that's one of the beauties of what I like to think of features of experience builder so what I'm going to do is let's go back into our extensions folder here and we're going to show you how we built this simple count widget here so let me collapse these and go into count features and let's go into our widgets tsx okay so you're gonna notice I have little more imports than before because what I'm using is data record data source looking for data source types I'm doing a feature query data source okay and then I'm also from the Jimmy core and then I'm also going to take advantage of using the ArcGIS package which looks for a feature layer data source so right off the back what I do is I create an interface for called ice dates and then I give it a property for force source data to import these classes for a feature layer data source in query and then basically what I want to do is I want to construct a query task right so here I have a let queue and then I assign it a query of 1 equals 1 object ID so in this example if if I don't have an outfield own optic idea it's gonna fail right so if you don't have if you have something like a unique identifier F ID and there's no object ID it's gonna fail but this is just an illustration of how this works so it's not really meant for production but basically from here we have this function query records right so we're going to inject properties for the parameter for all widget props the I M config the data source and it's a promise and we're gonna do a data source record represents a record in the data source K and then basically we're going to do is we're going to detect what type of the data source is is it a type feature layer okay if it is in return feature layer data source call this query count and do this query task and then do the get records else if it's a data source type of feature query we're going to do a feature query data source now you might be thinking why are you doing these two well some instances might be well you might be working with a service that's an ArcGIS service right or maybe you just want want to query that data set we have two different ways to to query the data and some instances you know if you're going to work with a feature layer data source or if you just want to query it you can use like one uses like the arc jet arc Jas rest yes and one uses the JavaScript API to do that okay but I think the most important takeaway here is you can look for different data sorts in perform how your widget needs to behave right so if I go back into here and let's just just delete this and let me add it and then if I go here and I add new data you're gonna notice that it uses web Maps web scenes feature layers URLs right it's looking for everything in there in some instances when you work with the map view it's only going to use the map widget so I'm gonna look for web map or web scene right so it's up to you as a developer to detect that data source so that's kind of this is what these patterns show here okay so here's where we this is that this is just preview where we get into the guts of our widget so here we have our class widget off the base widgets right and then we do some preload here for our data and then we return any query records here to use that particular data source and then here we initialize the initial State for I state's source data if it's undefined otherwise this state equals the state object here and then what we do is we pass that to the renderer features and we do a feature count and we look for if it's configured to get the read length and then we're going to return that from the default messages right so if we go into our translations here and default TSS we have this feature count here okay and now that's coming right here so there we go so there's our feature count so that's coming from that translations file okay so if we go back into our widget here the next thing we do is we pass that to our renderer right so if there's no data source detected it's common pattern you're always going to look for data so if it doesn't flag the user or if it's looking for a map flag the user select a data source then we use the data source of that and then we apply the source data to the state right and then we return that with the future count and then here is for our data source component to do actually do the query based upon our source data and then we use that data source of that and then here we call the andhis function to do that data source creation and then basically we bind those features to this to render that number yeah so that's one example another example is let's say you need to add records on the fly so let me let's see if I have one here we go you know just grab this one no let's see it wasn't I wanted maybe we could do this one and let's go to home so basically what I'm doing is I'm looking for a sample server here I should have should have should have had this all wire all right so let's let's grab this one here all right perfect so let's grab I don't know maybe fire perimeter all right so let's grab this control see so earlier I said you can create widgets at runtime so here's a widget that basically is also dependent on a map so let's go ahead and add a map here and let's go ahead and select our Old Faithful brewery map here ok and basically here we have a widget and the space can allowing the user to copy and paste a feature layer as a URL and basically it's going to add that at runtime to the map okay so to wire this up we need this map this widget to bind to this map and the way we do this is we just declare map 1 and you can see we have settings in here that allow the users to zoom to layer on this so if I hit let's hit save let's hit live view let's paste in our URL here hope this works let's see maybe let's see let's see it should be I mean hopefully it works did it work I know I just I don't know where the fire parameter is but basically it should zoom to that feature there let me see here let's just do this one all right we'll have to come back to that one but basically what it does is that it adds the feature at runtime to that so basically what's unique about this this particular this demo is we're loading the arcgis api modules as we need them ok now let me show you a pattern of that so if we go back into my add layers here we go into my source I'll go to my runtime here we go to widget tsx ok so here you can see we're importing this thing arcgis jsapi modules remember earlier I talked about if your widget doesn't solely depend on it you could load this when it's needed and that's basically what we're doing so as if we look at this same same workflow right we're creating our class extending base widget we're loading our our interfaces and we have a are types excuse me we we also have another type here and then we have our interface and then basically what we're doing is we're gonna give types to the modules we import from the API and then basically tell typescript which those are so for our feature layer this is using the ESRI feature layer here right query and then we're gonna pass in our state here right because we're gonna pass in the state earlier and then every time the input box value changes we're gonna call this function here all right so we're gonna handle this URL and then we're gonna set that state right because we got to reset that state if that target value changes and then we're gonna do a form submit on that value and then if there's any errors we're gonna say okay data source is not configured we can't do anything right common pattern and then if nothing was typed into the box we're gonna tell them please copy and paste in a future service URL and this is what we call a term called lazy loading rate only loaded if needed so this is how we we load the the the module so we're here loading feature layer query and space reference right and then we're doing a promise of this dot feature layer query in spatial reference through these modules and then we're gonna create the feature layer from the URL that's in the box for this state dot feature layer input and then we're gonna pass that to the gym you map view of the map and then we're gonna add that layer and then after the layer is created we're gonna zoom to the layers extent if the settings is set for that right so basically this is going to take the proper configs if it has that property zoom to layer it should zoom to the layer which is this boolean of true right and then we're going to do a query here of that to get the spatial reference and then pass that extent and then lastly we're going to set the state of adding the layer once if you know if we remove it from the box so we can add another one so that states always going to be reflected and changed and then lastly this is pretty consistent with our other patterns we're going to render that for that okay so that's an example of creating a widget at run time okay so let's get back into our presentation here so let's talk about message actions now this is a little different concept so what is the message action right so a message action is a way to support communication between widget or widget to framework and framework to widget right I like to think of it as a message action is a way to send data from your application right it's gonna send it somewhere and basically it's going to be a store right and the only source of information is gonna be in that store and think of these they're just plain JavaScript options or spring and what we use is we use Redux to help implement these message actions and what does Redux do it's basically state management using functional principles all the application state is stored in a single store object the state object can be read as a mutable object and what we mean by immutable is that that can only be changed by dispatching actions so since it's immutable you basically create a copy of it and create a new one from it so how do we do it well first we start with an action right which is basically an object and you dispatch that to the Redux store the action contains the the data the trigger that will be changed once the actions are dispatched to the reducer right this is just another JavaScript function it determines what part of the store is changed and it takes two parameters the current state and action action and produces the state of an application in this instance here an extent change so now that you have somewhat of a brief understanding of a redux let's talk about how message actions work in experience builder so basically a message has a messages type property okay and basically that indicates the type of action to be performed such as an extent change or data data record selection change and the only action describes what happened but it doesn't do anything right it doesn't describe how the application changes so what will happened is a widget will call message management to get the instance published message and then in the parameters for the message it will publish the message and then when you're gonna publish a message the widget should declare that in the public published message in the manifest JSON okay so let's talk about creating a message action first what you'll need to do is extend the apps abstract message action class and in here there are several methods and functions that will help you develop message actions the filter message type method is used to filter the available actions and in this code snippet it returns message type string selection and data records selection change the filter message method is just used to filter message in the message manager we have managers for theme for widget for data sources etc and they get setting uark component is basically you can use that to configure action based upon the message so if you're gonna be providing this to users and you like like in our example for the map there's gonna be some yet settings URI component to define what the action is based on the message okay continue on creating a message action the on execute method basically handles the logic for what you would like to happen for your message type it basically selects the action based upon the message type and it sends it from the application to this to the store using the get app store function and then using the dispatch property this basically just this bit this bait that does this what it does it dispatches the Redux action and allows a state to be updated okay so let's go into an example of how that works all right so if I go back into my browser here and I go into let's see experience builder here and now we're gonna go to local we're gonna do here alright ok so here we have an example this sample demonstrates how widgets communicate ok so here we have we basically have three widgets here on the screen so basically this widget will publish the string selection change message so I'm go ahead and select Colorado this widgets gonna listen to this string selection change right and then it's going to do the data record selection change message to do a query ok this widget will publish the data record selection message change to this widget so go ahead and select Montana here you're gonna notice it changed that same if I do Alaska okay so this is an example of how messaging works so let's go into our IDE here and let's go into this particular widget here so we're going to go into our extensions widgets let me collapse this collapse this and let's find our widget so we have this widget called subscribe widget now this widget doesn't have any UI for the configurations right so basically what's happening here is we import this the Massa's we need which is abstract message message type the message get up store app options string selection change and data record selection change mission from Jimmy core ok then we're going to define some interfaces here for the config for the change message of we're going to declare that fill name it's going to take a string another one for config future change message and that's going to be filled name of a string and a query fill name of a string and here we're extending that abstract message right and then like we saw on our slides we have a filter message type takes a parameter of message type right so you could see that's inheriting from API reference here you're gonna pass in the message which ID the string and the boolean then gonna return the message type which is a string selection change alright and record selection change and then you're gonna find it within the index and then basically you could see there and then we're going to do the the filter message for the message the boolean to return true in here we're gonna say okay for the getting's component URI it's going to look for this query pass action and then on the on the execute write method here in function you're gonna say okay queue like Q equal action config for that interface we define for query change we're gonna do the fill name for the message and then we're gonna basically doing switch so if the message type is a case of string selection do this get the filled meme if it's for record selection change query the filled name and do this and basically do a change record and get the data for that change message based upon that filled name and then what we do is we have to dispatch that to the store so you're going to have your app actions and this is where we're going to change the state of the the widget for this widget ID within the query string and then pass in the cue of whatever the case was from there right so that's how it works so if we go into our manifest here you're gonna see that our manifest has message actions the name is query okay and then the URI is actions query so this is gonna be the name of our action so any it's where we call it it's going to be called query from there and that's all that works all right so let's get back into our presentation here okay now what I want to do is I want to talk about debugging right because let's face it we can't debug we're pretty much hosed so the first thing that you're gonna do is like anyone's you're gonna select your idea of choice our team pretty much uses all VideoStudio code and it's a great option because it has typescript built in by default in its in it's great it's open source and it's it's the one that we use and I like it a lot but if you have one that's your favorite that's that's you could use that as well so the next thing you're going to do is you're going to add anything you do is going to be in that client folder which showed you before you always want to make sure you add that to your AI dee' workspace because what that's gonna allow you to do is reap all the benefits of atella sense you can see the comments for API reference you can look up definitions and of course it helps you with Camco completion etc so you always want to make sure you add that client folder at your workspace and then we also recommend these extensions presidio studio code the first ones that tell sense for CSS class names this basically allows you to do CSS class name completion and the last one we also recommend is the vyas code style components and that's used for syntax highlighting first styled components okay so let's go ahead and walk through a simple debugging exercise here because I got any want to leave some time for my colleague here alright so let's go into experience builder here and yeah let's say we let's just use this one let's see all right yeah let's use this one all right so let's go command J here and let's go into source first thing you're gonna notice is you're gonna say okay you see this web pack you have web pack learning that's perfect alright so what I'm going to do is I'm going to do command P and you're going to type in widget tsx and the one that you're going to want is the one that has the number with it at the end widget TSX this one right here okay alright and then here what we could do is we could just go in here and set all right I want to look at I want to do some debugging so let's look at our state see if this loaded here and then we can see if there's changed here and we can see if the active view changed right all right so let's just go ahead and refresh this changed okay hold on because I saved this widget differently all right so let's go back in here widget tsx here all right so let's refresh this real quick so here you can tell it's it's getting some information here so if you look at the scope and you can expand this you have your local variables and here you can see what's in here oh it's a layout it's going to tell you updated is mounted the state and then another important area is the Global's right so these are Global's that we're experienced places a few these these are basically what I like to think they're convenient variables you so you can inspect the current status of different things in your experience right so if I go ahead and scroll down here I'm gonna look for let's see down here there should be some for widgets and data source manager yep here we go so here are some from here you can see the App Store you could see data action manager message manager you can see all kinds of stuff here and basically these so if you look for a data source manager here this one right here basically that gets you the current data sources in the widget there's another one in here for widget manager which basically here's the widget manager that will tell you a variety of properties about which including them for widget is loaded or not okay and then there's another one called session manager here these are all global and it basically tells you you could see who's logged in from there okay so these are some just simple ways to debug but as you can see you can see all the dev tools and of course you can also add the react tools to to look to see from a nested structure to to see what what the components look like so the easiest way to deploy a project experience builder is I hit save and then I hit download right so download also this appearance is not published so basically you got to publish it right so publish is basically publishing it in your local instance of experience building and then you go ahead and you hit download and then basically you download that package to your web server and then you're ready to go so with that I'm done talking for the bit and I'm gonna turn it over to my colleague e-way all right all right thanks David so in the following section we will be folks focused more on the UI development you really hit topics so first one we're going to see how to develop and style the UI in the second part we will see how to create a custom themes so first let's take a look at how to develop and design the UI of a widget so normally there are three steps involved in creating the UI for your widget first you need to add the HTML HTML structure to the widget the HTML structure for the widget defines basically it's layout at a static content second you may want to add CSS classes to elements in the Dom tree of the HTML template to either utilize existing global CSS classes such as for background colors font sizes spacing and etc or to add a specific class name to an element in order to add red any / / recess legislature and the last you may want to add the custom CSS styles to your widget so next I'm going to walk through these steps one by one and follow that we will see a lab demo on how to create the UI for the widget so first one is to create the widget a HTML template so the syntax by great act uses for writing the HTML templates is called JSX it is very similar to the two reading normal HTML but with full JavaScript capability baked into it the HTML code is usually defined in the return statement you said over widgets a render function and one thing I would like to mention is that in use Muse builder we provide a UI library for developers to use in their bridgit development such as the basic UI components like buttons dropdowns improves navigation Motorin etc and also some of the UI components such as resource selectors expression builder and in the future we're going to add more map centric components so you can utilize these chimĂș UI components instead of creating your own from scratch and next you you may next is to add the CSS classes to the widget and in react the CSS class names can be added to the Dom elements through the class name attribute also in experienced builder we provide a group of utility classes or you can call them modifier classes to help you to quickly apply a style from the theme to a UI element for example you can add a class name called BG - primary to the container of your widget to let it use the primary color from the theme as is background color these utility classes follow the same naming convention as the the ones from bootstrap for example the background colors text colors borders sizing shadow and etc as seen in this screenshot here last one which is to add the CSS Styles so so there are basically three approaches to do so in experience builder first one is to create a separate CSS or process file and you can add the styles in those files and import the file as a module inside of the widget this is this more like the traditional way of reading census second one is the to utilize the style attribute from JSX this is very similar to reading Illinois CSS you can't define the census as an object and assign it to the style attribute on an element the last one also which is the recommended way to write a CSS is to use the CSS prop from emotion which basically is the way of using a reading CSS in JavaScript it the reason is it is the most flexible and powerful way between all three and I'm going to explain this later and by the way you use pewter it is also optional to include theme burbles in reading your CSS for the widget utilizing the theme verbose will make the UI of the widget to be dynamically updated with the selected theme and ensure that look and feel is consistent across the app so theme variables are available as an object in which is props you can tell it by by typing of this that props toffee and the squish are here shows a simple example of doing so next one is we are going to quickly see a demo on creating a widget UI right so let me switch to the browser here so I already have the builder open and here I have a very very simple demo widget add it to the canvas only does is basically just you click this button and it's going to give you a random number from 1 to 20 and that's it and it is only for demo purpose and if from the UI you can see the UI is very simple it doesn't have much Styles applied so in the co-pays over here within this demo Bridget folder and within this a TSX file here's the the code we have so far for the widget so at the top we are importing the required components and modules from g/mol core in the G mu I and we have a state that has a member called random number so basically we are updating this number when we click that button and then this the the start state of this number is five and we have a simple function that returns a random number to the widget and over here within the render function here we have a very simple HTML structure defined over here were simply has a taro it has a heading tag that contains a number and now also a primary button from a GUI so next we are going to add some class names to the widget what I'm doing over here is to basically add these utility classes to the widget for example we add the LED background to the widget we make the text to appear as blue which is the the primary color and we add the padding the shadow make the text to be center-aligned and also some border radius okay so if we save the file go back to the app then we refresh the app and we log in again all right so you see the widget and now has some pretty fun styles already applied to it so now you can see the boundary of the container and next what we are going to do is we are going to add some CSS that was specifically for this region by using the the CSS in JavaScript which is the emotion library from from experience builder so first one we are going to do some required steps first one is we need to include this JSX fragment then we are going to import CSS and J's X modules or classes from Jammu por then we are going to actually going to write some of the styles so over here I'm going to declare a function which basically is going to return a CSS string okay so as you can see over here we are referencing the the theme props from the widget and over here the first six lines of the CSS code is basically doing the same thing as the class name we have added over here then we add some eyes trust styles to the button which is to make it a to appear as you run it and also when else Howard is going to zoom out a little bit and next one is a very very nice feature from emotion which is which is that you can add if you can add logics yeeesss ready over here for example that we are we are watching the the current in run run random number if the number is greater than ten the text color we'll be green and if not it will be red then the very last step is to assign this function to the CSS attribute on the container of the widget and a by the way we can and commit we can come out how this class name so save let's go back to the app refresh then we are going to see okay so you can see now five is below ten stories up here as red and if we click give me okay so 20 is greater than ten foot then it appears on-screen let's go back to the slice so next one you know for your section we are going to walk through how to custom nice themes use muted okay taking a look at this chart this basically explains the the workflow of how the theme is applied in spins builder for okay so at the top left we have the theme framework it contains some of the core variables including colors found border and etc variables and those variables are referenced by the component variables which will be used in the style modules which are functions that will generate CSS files on the fly and those CSS files will be used by the actual UI components to apply the styles to the components and it since the widget is mostly composed with UI components that's how the widget are adapting the this the theming from from the framework and as the demo has shown that widget itself can also has its own style added to it so how to do it so basically there are two approaches to create a new theme first one is to overwrite the default theme variables the second one is to provide extra style modules or style sheets to the theme first let's take a look at how to customize a theme by overriding the theme variables this is also the most common is a way to create a new theme in a spirit builder there's a default theme that contains all of the verbose in the JSON format as shown in the screenshot here and in a custom theme we can add verbose overrides instead of the verbose that JSON file for example we can change the primary color from blue to red over here so at the runtime the the theme system will merge the custom JSON object with a with a default one and generate a new one for the app to use so as you can see when the custom theme is applied the the primary color has changed from blue to to red all right the next two methods are to provide customs stashes or style modules to the cusps to the custom theme folder so first one is more of the traditional way which is to provide a separate CSS file in UNIFEM folder basically you can write any CSS styles in this file and the file will be dynamically inserted into the head tag of the app in this example we add some simple CSS styles to the body tag to make it to make its background blue text to read and font to to this impactful all right so this is the result of of the theme after the the style has been applied please note that in the CSS file there is no access to the theme variables so there are pretty much fixed values and the next method is to define styles as modules so instead of adding a style that CSS file in the folder we can add a style that TS file in the folder similar to the widget UI demo the CSS is defined within a function and as port the the function is exported as a module tool to the theme system to use the cool thing about this approach is that you can use all the fin variables from the system in your CSS reading and also the styles created are scoped so the example shown here is basically a rewrite of the same styles from the previous slide but you can tell that the difference is that the styles will be will be changed then dynamic dynamically according to the theme you selected for example this theme a has this blue background color and the red test color but when it is changed to thin B those colors will be changed dynamically all right so at the very last we're going to see a quick demo on how to create a custom custom theme all right so basically let's show the the demo folder here so within your extensions directory I have already added a demo theme folder over here I know within a folder first we have this verbose dartium file in this just fell we are doing some simple stuff first one is to to change the primary color to red then we going to use a different family which is the rowboat oh we are going to add later and make the font size smaller and also we are going to change the primary button style to a different way so let's go back to the Builder using the same sample if we select this demo theme you can see that first their test colors have been changed to red and you can see the primary button styles has completely changed okay since this this is the the power that overriding verbose can give you next one is we are going to to work with in this style that ESS file so first first whoa we are going to do is we are going to actually import this custom font with in this global styles function so i'm going to uncomment this function and also this s port so well this expert does is basically it's going to tell the theme system to use this function to apply the CSS as a global style so save go back to the go back to the app as we refresh we can see if you can tell the difference that the font family has changed to a Roboto and the last one I'm going to demo is to override the default styles for a specific component the example I'm using here is the button a component so basically what I'm doing here is pretty much just change is font size to a to a bigger font size and then the same thing here we are going to export this function as a module for the as a style module for the button component to use so save go back to the app let's refresh again you will notice notice that the button has been bigger so it's not only working on this button but any other button components for example let's add a new button to the app that you can see the phone says also becomes bigger all right so that's all for my part that to you David great thanks you way so one thing before we go I just wanted to redeem myself to show you that this demo works so I'm gonna go ahead and copy a feature layer here and add it and should zoom to it and there we go so just needed to provide some redemption there okay so before we go I always wanted to provide you some valuable resources first thing always go to the developer website experience for developer website to get the latest information regarding our technology we have API reference and we have links to sample snippets with that we have a samples repo for experience builder that will continue adding additional samples with widgets and maybe some config files to show you how other areas of our products work with extensibility as far as like data sources so we'll include some some some code that might necessary include UI because it's illustrating the concepts to use like data sources and other things so stay on look for that and for those who are new to react or redux there's great information out there much more in-depth and I believe value that I could teach you that you could find on there and of course we always want you to go to the Geo net community for experience but we're always constantly listening into the channel and trying to answer questions as it may be and with that we like to thank you for attending the session and hopefully you've learned something new thank you okay
Info
Channel: Esri Events
Views: 4,535
Rating: 4.647059 out of 5
Keywords: Esri, ArcGIS, GIS, Esri Events, Geographic Information System
Id: UIqMqnfTlWQ
Channel Id: undefined
Length: 68min 19sec (4099 seconds)
Published: Tue Apr 07 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.