Select to view content in your preferred language

Attribute Inspector / Feature layer with not-null constraints

1425
5
04-18-2012 07:16 AM
HarryGibson
Emerging Contributor
As the title says, I have a feature layer, which is based on a feature class where several fields are constrained to be NOT NULL. I'm hoping to use this to provide the back-end to a volunteered geographic information type map. Likewise I am hoping to use the template picker and attribute inspector to create the features.

The default workflow in the samples is for the feature to be created using applyEdits with the clicked geometry and null attributes when the map click or draw end event fires, then to display the attribute inspector on this feature to update them. But as far as I can tell I can't take this approach as I can't create the feature with null attributes due to the feature class constraints.

The workflow that seems to be sensible is for a map onclick event to create a new feature as a graphic, and then display the attribute inspector on it in an infowindow, with a submit button. When the fields are populated (and validated), pressing the submit button will be what calls applyEdits on the feature layer, which can now be done as all attributes are present.

This is pretty much what seems to be done by the Citizen Request Sample template app which "rolls its own" content for the info window to populate the fields. But i'd rather use the template picker and the attribute inspector to do the attribute editing, particularly because of the ease of styling, working with coded value domains etc, and so that the app isn't totally tied to the schema of the feature class like it is with that template.

But the attribute inspector seems to be inherently tied to feature layers rather than graphics.

What am i missing? Any suggestions as to a better way to accomplish this? The main point is that I don't want to get features submitted that don't have all the attributes I need, hence the use of the constraints when I set up the feature class.

Thanks! Harry
0 Kudos
5 Replies
HemingZhu
Frequent Contributor
As the title says, I have a feature layer, which is based on a feature class where several fields are constrained to be NOT NULL. I'm hoping to use this to provide the back-end to a volunteered geographic information type map. Likewise I am hoping to use the template picker and attribute inspector to create the features.

The default workflow in the samples is for the feature to be created using applyEdits with the clicked geometry and null attributes when the map click or draw end event fires, then to display the attribute inspector on this feature to update them. But as far as I can tell I can't take this approach as I can't create the feature with null attributes due to the feature class constraints.

The workflow that seems to be sensible is for a map onclick event to create a new feature as a graphic, and then display the attribute inspector on it in an infowindow, with a submit button. When the fields are populated (and validated), pressing the submit button will be what calls applyEdits on the feature layer, which can now be done as all attributes are present.

This is pretty much what seems to be done by the Citizen Request Sample template app which "rolls its own" content for the info window to populate the fields. But i'd rather use the template picker and the attribute inspector to do the attribute editing, particularly because of the ease of styling, working with coded value domains etc, and so that the app isn't totally tied to the schema of the feature class like it is with that template.

But the attribute inspector seems to be inherently tied to feature layers rather than graphics.

What am i missing? Any suggestions as to a better way to accomplish this? The main point is that I don't want to get features submitted that don't have all the attributes I need, hence the use of the constraints when I set up the feature class.

Thanks! Harry


When you create a feature (graphic), you could input a default value such as "" for those non-null field.
var Attributes = {
              field1: "",
              field2: "",
              .....
            };
var newFeature = new esri.Graphic(geometry, null, Attributes);
// then apply attributerSepctor, so when you apply featureLayer.applyEdits (newFeature, null, null)...
0 Kudos
HarryGibson
Emerging Contributor
I could do that, but for that matter I could not have the not-null constraints on the fields in the first place since I run the database too.

It seems to rather defeat the point of using the database as it should be, to ensure that checks are applied to the data at the point of creation so they are guaranteed to be "valid". Thus preventing some other client from (maliciously or otherwise) sticking loads of random and incomplete stuff in. Surely that is just common sense database design?

If on the other hand the attribute inspector could produce a Graphic (perhaps having automatically generated the attribute schema for that graphic from the feature layer) then the client could more easily generate a valid feature before submission.

As it is, it seems that the workflow (if we want to use the pre-made editing widgets) is to generate and store in the database an invalid feature, having crippled the database to make this possible, then update the feature in an entirely separate operation after it's created to make it valid. Whilst hoping that nobody comes along and generates invalid features by some other means, or that our client doesn't suffer some kind of error in between making the feature and modifying it.

Just seems rather back to front to me - is this really the intention?
0 Kudos
HemingZhu
Frequent Contributor
I could do that, but for that matter I could not have the not-null constraints on the fields in the first place since I run the database too.

It seems to rather defeat the point of using the database as it should be, to ensure that checks are applied to the data at the point of creation so they are guaranteed to be "valid". Thus preventing some other client from (maliciously or otherwise) sticking loads of random and incomplete stuff in. Surely that is just common sense database design?

If on the other hand the attribute inspector could produce a Graphic (perhaps having automatically generated the attribute schema for that graphic from the feature layer) then the client could more easily generate a valid feature before submission.

As it is, it seems that the workflow (if we want to use the pre-made editing widgets) is to generate and store in the database an invalid feature, having crippled the database to make this possible, then update the feature in an entirely separate operation after it's created to make it valid. Whilst hoping that nobody comes along and generates invalid features by some other means, or that our client doesn't suffer some kind of error in between making the feature and modifying it.

Just seems rather back to front to me - is this really the intention?


You can also set up the layerInfos in a way that you can validate the field input. ESRI has a sample: http://help.arcgis.com/en/webapi/javascript/arcgis/help/jssamples/ed_attributeInspectorValidate.html
0 Kudos
HarryGibson
Emerging Contributor
Thanks, but again - unless I'm being really dense here - that is calling applyEdits when you click on the map and creating a feature in the database with null / empty values in the attributes. Which is then edited, in a separate operation. Unless of course, I click away; go and make a cup of tea and forget what I was doing; etc, at which point the data is left with an invalid record in it.

The ValidationTextBoxes are just used to check that the attribute data which are then used to _edit_ that feature are appropriate. Using them is sensible, and a good thing to do as well, but doesn't address the problem.

Creating a feature - geometry and its associated attributes - should be viewed, or at least able to be viewed, as a single transaction. It's not right to have a point without attributes, any more than it is right to have attributes without a point. You don't send somebody an email containing only every second sentence, and then maybe send on the remaining sentences at some arbitrary later date!

Given that point of REST is that it is stateless and there is therefore no continuity guaranteed or implied between the operation where a feature is created and one where it is edited, this is surely even more important than if we were creating the database row using an INSERT statement at the command line - we shouldn't rely on the client to "remember" what it was doing and guarantee to apply one operation after applying another.

Anyway, I don't want to sound like I'm dancing on pinheads. I thought this seemed such an obvious bizarreness in the way that the workflow was implemented that I must be missing something... but clearly not. If it's just me fussing then I'll have to do it "manually" - like the team who wrote the Citizen Request sample obviously chose to do as well.
0 Kudos
HarryGibson
Emerging Contributor
I thought about this a little more and I'm sure it's got to be a weird design decision.

One big reason for using the Attribute Inspector is its automatic respect for coded value domain fields. Why would ESRI design a widget specifically to help implement one database-side feature that is designed to ensure data quality (coded value domains) but which cannot be used when another such feature (not-null constraints) are present.

This has got to be seen as a bug: basically the editor widget / attribute inspector widget cannot be used to create features where the underlying feature class has not-null constraints, without significant hacking that defeats the point of the easy-to-use widgets. Whereas they specifically ARE used to create features where constraints of another type (coded value domains) are in place.

Better options would surely be
a) have the widget work out what fields are required to be present, using a similar mechanism that it uses for populating the coded value domain dropdowns, and create the feature locally before submitting it when complete.
or
b) Have ArcGIS server expose an initiateEdits operation which creates a temporary feature on that side in scratch workspace, without committing it to the database; this can then be updated further (based on a returned id) before calling applyEdits to commit it.
0 Kudos