Select to view content in your preferred language

Inject value during editing workflow

91
3
Jump to solution
Tuesday
JeffreyThompson2
MVP Frequent Contributor

I am working on an application designed for users to make some simple feature layer edits. The users have full add/update/delete privileges. Another portion of the application generates a string value. I would like to have this value automatically included as the value of one of the fields whenever a user makes an edit. I don't care if the user sees this value or not, but the user should not be able to change it.

In a similar application, I was able to do this using @JoelBennett's solution from this post.

editorVM.watch(['state', 'featureFormViewModel.feature', 'featureFormViewModel.state'], () => {
  if (editorVM.state == 'creating-features' && editorVM.featureFormViewModel.feature && editorVM.featureFormViewModel.state == 'ready') { 
    window.setTimeout(function() {
      editorVM.featureFormViewModel.setValue('PhoneNumber', "999.999.999")
    }, 200);
  }  
});

But there are two complications for this application.

  1. This time I am using the Editor Component, not the Editor Widget, and the widget view model does not appear to be accessible through the Component.
  2. This application also has a FeatureTable Component that is editable and I also want the value injected when editing is done through the table.

Feature layers have the edits event that can be watched for, but it happens after the applyEdits() method completes. If I try to use applyEdits() inside this event, I will create an infinite loop. The code I want to write would intercept before the applyEdits() method is called, inject my value into the attributes and then proceed saving the edits.

Goal: Automatically add string variable to the attributes of a Feature Layer whenever it is edited in an application.

Restrictions:

  1. Users cannot alter this value.
  2. Must work with both Editor and FeatureTable Components.
GIS Developer
City of Arlington, Texas
0 Kudos
1 Solution

Accepted Solutions
JoelBennett
MVP Regular Contributor

An ugly but effective way to intercept a function call prior to its execution is to store a reference to the function, override it with your custom processing, and then call the original function at the end like so:

var featureLayer = new FeatureLayer({
	//etc
});

featureLayer.originalApplyEdits = featureLayer.applyEdits;

featureLayer.applyEdits = function(edits, options) {
	//do whatever you want to the "edits" object

	return this.originalApplyEdits.apply(this, arguments);
};

View solution in original post

0 Kudos
3 Replies
JonathanDawe_BAS
Occasional Contributor

in terms of accessing the viewmodel for the widget I have found that it is seemingly possible via an undocumented property on the web components. I have implemented some additional logic to hook into some viewmodel events/properties on the Features Component. 

function isWaitingForResult(element: HTMLArcgisFeaturesElement) {
return element.widget?.viewModel?.waitingForResult ?? false;
}

 

0 Kudos
JoelBennett
MVP Regular Contributor

An ugly but effective way to intercept a function call prior to its execution is to store a reference to the function, override it with your custom processing, and then call the original function at the end like so:

var featureLayer = new FeatureLayer({
	//etc
});

featureLayer.originalApplyEdits = featureLayer.applyEdits;

featureLayer.applyEdits = function(edits, options) {
	//do whatever you want to the "edits" object

	return this.originalApplyEdits.apply(this, arguments);
};
0 Kudos
JeffreyThompson2
MVP Frequent Contributor

Thanks, @JoelBennett. It works. For the record, here's what my completed function looks like.

 featureLayer.originalApplyEdits = featureLayer.applyEdits
 featureLayer.applyEdits = function (edits, options) {
     console.log(edits, options)
     if (edits.addFeatures || edits.updateFeatures) {
         const features = edits.addFeatures || edits.updateFeatures
         features.forEach(feature => {
             feature.attributes.attributeName = value
         })
     }

     return this.originalApplyEdits.apply(this, arguments)
 }

I don't know if the if statement is necessary, I just threw it in case.

GIS Developer
City of Arlington, Texas
0 Kudos