Looking to customize the edit widget form for a specific feature layer

1710
2
04-13-2017 10:54 AM
ScottLehto2
New Contributor II

Hi, Well have I got a newbie question. I am new to WebApp Builder and JavaScript but I do have some experience in ArcGIS and C#.   
What I was looking to do is develop/customize an edit widget to be used exclusively for a specific feature layer.
Most importantly, I would like to substitute a lot of the text boxes in my edit form/widget for the combo boxes/filteringselect boxes. It sounds easy enough, but I am struggling to find info.
If anyone has completed this and could offer me some pointers, I would be very thankful.

0 Kudos
2 Replies
DavidWendelken
Occasional Contributor

Edited to correct the class name, thought it might be Popup before.

I believe the esri AttributeInspector class is used to edit data for a record. 


Not sure how to change it yet as calling it appears to be built inside the feature layer class, not a web application builder widget.

I do know that the constructor function in AttributeInspector receives two parameters.  The first has a layerInfos field in it, which is an array of editable layers.  Each layerInfo in that array has a fieldInfos array which contains instructions to the AttributeInspector about the fields it is to edit.  For example, seting the isEditable field to false will make the field read only and gray it out.

FYI: If you need to set defaults BEFORE the record is actually put in the database (and afterwards the popup edit window), check out how to set custom default values on new object in Edit widget 

That's the best I can tell you at the moment, I'm still figuring it out.  Hope this jump starts you a bit.

DavidWendelken
Occasional Contributor

I've done a good deal more work on the Edit widget since my last reply.

I created a java script class to act as a CustomRecordHandler.  My intent was to keep as many changes out of the widget.js file as I possibly could so it would be easier to upgrade to newer versions of the Edit widget.

So, I instantiated CustomRecordHandler in the widget.js variable list.  (Naturally, that meant it had to be mentioned in the define/function list for the widget.js module.)

I created a call to the _customRecordHandler object in the widget.js startup, onBeforeApplyEdits, _worksAfterCreate and _onEditorPopupShow methods.   That way, I only had a few lines of code to replicate in order to move to a new version of the Edit widget.   A lot of the info you may need is only available in the widget.js context so be sure to pass in what you need to your various methods.

The onBeforeApplyEdits was the only really tricky event to handle because it is NOT called asynchronously and some of the ESRI code I wanted to execute at that point in time REQUIRED an asynchronous call.   In order to get around that problem I created a custom c# web service that could be called synchronously and didn't return results until it was done.  I don't like that particular kluge, but the only fix would be to alter the call to onBeforeApplyEdits to be an asynchronous one -- and doing that with minimized code was more than I was willing to attempt!

Tasks I charged the events to achieve were:

onStartup - compare the list of layers in the variable holding the Edit widget config file with the list of layers actually on the map.  If the layers actually on the map include an editable layer (which you can determine by checking the layer's capability property) that isn't in the config file-based object, I call I routine to add that layer to the config file-based object.  (The format of the data to put into the config file object is pretty intuitive.)   I also tell the map to call the same method if someone later adds a new layer to the map using the layer-add-result .  (I have to bind the method with the widget's this context before I hook it up to the layer-add-result call, or it won't have access to the info that method will need.)   That way, it doesn't matter whether the user adds an editable layer before or after the Edit widget is invoked.  PS - the map has a graphics layer that's there for some purpose and you'll want to ignore it.  I found that checking for an undefined layer capability property worked for that purpose.

_worksAfterCreate - add the custom fields to the editor object.  I was adding buttons to do simplify common tasks for our users.  I created these items but hid them because they shouldn't be used for all layers, just some of them.

_onEditorPopupShow - I changed the display settings for the items I created in _worksAfterCreate if they should be used for the layer being altered.   I can't definitively state that splitting up the work between the _worksAfterCreate and the _onEditorPopupShow events was necessary, but it seemed the right thing to do at the time. 

onBeforeApplyEdits - pass the widget context, plus the results of a call to this.getOriginalAttributesBeingEdited(), plus the edits parameter the method receives to my custom routine.  This is the workhorse for the code that I added.  I was able to set default values that had to be determined at run time instead of design time.  As I mentioned before, you'll have to avoid or hide asynchronous calls at this point in time, the ESRI code will just ignore and proceed without waiting.

I made one other mod to the Edit widget, but in the FilterEditor.js file.  I added a field where a user could type in a latitude, longitude (or other coordinate method) into it and a plot button in the _createFilterTool method.
The Edit widget, out of the box, will let the user select a template from the list of editable layers and click on the map to create the object.   In our case, sometimes the users are entering data where they already know the coordinates the point is supposed to be created at, so making them navigate to that location on the map is time-consuming and unnecessary.   If the user has selected a template and entered a coordinate, pressing the plot button will call the same CustomRecordHandler object.  It calls a method that receives the FilterEditor.js this object, the coordinate value that the user entered, the this._editWidget.editor.templatePicker.getSelected() results, and an indicator that an insert is happening.  The customRecordHandler object zooms to the location on the map and then calls the chosen template's featureLayer.applyEdits method, supplying a new graphic at that coordinate in an array in the adds parameter slot, plus some callback functions to resolve or reject the promise results.

Hope this helps some folks customize the editor object to their heart's content! 




0 Kudos