Populate an attribute using Forms in AGOL map viewer

314
13
2 weeks ago
Labels (1)
SamanthaAPCC
New Contributor II

I'm hoping I'm close!  I was trying to do a similar thing using an Arcade Expression for symbology but I can't select the most recent feature.  So instead I'm writing the data to a new Field using Forms.

I have two datasets, a point dataset of sampling locations, and a corresponding pond polygon layer.  

The pond polygon layer will be public facing, and the symbology will reflect data gathered in the survey that populates the point feature class.  I have created a new, blank field in the pond polygon feature class that I'm hoping I can populate given a few criteria from the point layer.  Below is my arcade expression that I'm using in 'Forms' to calculate that blank field.  I need the pond to correspond to the correct points (hence the buffer in case they are slightly outside of the polygon), and I need the dates of the samples to be within 30 days.  As an option, if Intersect with a Buffer won't work, I do have an ID field that is identical between the point layer and the polygon layer.

 

 

// Define a Featureset (status) from the layer "Cyanobacteria_Public View" in the $map 
// that contains the attribute ['cyano_risk_tier']

var status = FeatureSetByName($map, "Cyanobacteria_Public View", ['cyano_risk_tier', 'fluorometry_date', 'final_review'])

// Define a variable (risk) to store the value we want
// Get the value by Intersecting the pond polygon location 
// with the FeatureSet "Cyano Ponds Public View", or status

var risk = Top(OrderBy(Intersects(status, Buffer($feature, 30, "meters")), 'fluorometry_date DESC'), 1);

var edit_datetime = Date(status['fluorometry date']);
var now_datetime = Now();
var days_dif = DateDiff(now_datetime, edit_datetime, "days");

// If the current location intersects the pond, 
// return the value in the field ['cyano_status']. 
// Otherwise, return a null value for areas where there is no intersecting polygon

var result = "No updated information";
if (!IsEmpty(risk) && (days_dif <30)) {
    return risk['cyano_risk_tier']
} else {
    return result
}

 

As a next step, if this works to populate the field in the pond polygon layer, I would also like to add on to this expression to allow for the following situations.  Occasionally, there are two sample sites for the same pond in the same day.  One sample site may have a lower 'cyano risk tier' than the other site.  I would like to default the 'cyano_status' to the higher of the 2 risk tiers.  So for example, if one sample site the risk is 'Acceptable', and at the second sample site the risk is 'Potential for Concern' (and these sites were sampled in the same day), I would need the overall risk for the pond to be 'Potential for Concern.'  In total there are 3 risks in the tier.

 

0 Kudos
13 Replies
SamanthaAPCC
New Contributor II

I've been reading other community posts on this topic and have slightly altered my expression... it's still not populating the field however.  Below is my modification, not sure if this is heading in the right direction.

// Define a Featureset (status) from the layer "Cyanobacteria_Public View" in the $map 
// that contains the attribute ['cyano_risk_tier']

var status = FeatureSetByName($map, "Cyanobacteria_Public View");

// Define a variable (risk) to store the value we want
// Get the value by Intersecting the pond polygon location 
// with the FeatureSet "Cyano Ponds Public View", or status
// var risk = Top(OrderBy(Intersects(status, Buffer($feature, 30, "meters")), 'fluorometry_date DESC'), 1);
// Not sure if this works
// Instead, try to match by CCC GIS ID

var CCC_GIS_ID = $feature.CCC_GIS_ID;
var IDS = "CCC_GIS_ID = '" + CCC_GIS_ID + "'";
var RelatedReads = Filter(status, IDs);
var numrelreads = count(RelatedReads);
if (numrelreads == 0){
    return "No updated Information";
} else if (numrelreads !=0){
    var LastSampleDate = Top(OrderBy(RelatedReads, "fluorometry_date DESC"), 1);
    var edit_datetime = Date(LastSampleDate);
    var now_datetime = Now();
    var days_dif = DateDiff(now_datetime, edit_datetime, "days");
    if (days_dif <= 30){
        return status['cyano_risk_tier']
    } if (days_dif > 30){
        return "No updated Information"
    }
0 Kudos
JosephRhodes2
Occasional Contributor II

Have you tried logging those variables to the console, e.g., 

Console(RelatedReads)

etc.?

That might help you understand the values being generated by the expression to make sure your logic is getting the inputs you expect.

0 Kudos
SamanthaAPCC
New Contributor II

Thanks, I just tried using Console and it is reflecting the language I want (writing the text 'No updated information' for example), but it still isn't populating the field in the attribute table.

 

0 Kudos
SamanthaAPCC
New Contributor II

I'm realizing that I may be mis-interpreting the capabilities of Forms.  I need to populate a field in a polygon layer (that doesn't get added to, only overwritten) using data that gets updated in a point layer via Survey123.  I don't think Forms will do this.  I'm also stuck because I can't OrderBy most recent date in Symbology either, which is crucial, among other factors, to populate the correct symbology of the pond.  I found your article on "Easy How-To: Symbology Using Related Records".  This might be my only answer, although I'm definitely a beginner at python.  Unless you know of another way to write a symbology expression so that the most recent date from the data gets chosen?

0 Kudos
JosephRhodes2
Occasional Contributor II

I see - it sounds like you're trying to populate values in bulk for the whole table. If so, then you are correct, Forms is not meant for this. What you should expect from Forms is that when you go to edit a feature in the map (e.g., by clicking on it then clicking Edit in the popup), the value for the field where your expression is configured will be pre-populated with the value returned by the expression.

The Arcade visualization profile doesn't support FeatureSets, so I don't know of a way to dynamically set the symbology in the way you're describing. Attribute Rules are not supported on hosted feature layers, so that's out as well.

AFAIK, you'll need to calculate the values you want to use for symbology, either manually or with Python.

0 Kudos
SamanthaAPCC
New Contributor II

Thanks Joseph, 

This is the exact path I've gone down, first trying arcade in symbology, then looking into Attribute Rules, and finally Forms.  The whole project involves 3 Surveys used to collect field and lab data over the monitoring season.  Each of the 3 surveys have information that we would like displayed in a single pop-up on a public facing map (they have a UniqueID that connect all 3).  The survey sites themselves are point locations, but the map will just display symbology/information for the entire pond (polygon).  I have tried to join one of the surveys with the pond polygon through a joined View, but the issue I'm running into there is that as more surveys are collected, the polygon is not drawing with the data from the most recent date.  In the past, this whole process was done with excel/csv tables being filled out by field staff, and a number of python and models being performed in ArcPro as scheduled tasks.  However, since this relies on a computer always being turned on, we were running into issues with this process, among other issues with transforming a csv filled out daily by a number of staff members.  The solution this year has been to create the online Surveys and shift the data collection to using tablets in the field, which will be a big improvement.  However, I'm now running into the struggles of recreating this public facing map in a way that is expected by the program.  I'm a definite novice at python, but it's looking like this may be my only solution.

0 Kudos
JosephRhodes2
Occasional Contributor II

Just noticed that you have matching IDs (I missed that on the original post because I saw you were doing an intersect). In that case, a joined view should work. Did you set the join operation as one-to-one, only keep the first matching record, then sort by EditDate descending?

0 Kudos
SamanthaAPCC
New Contributor II

I've thought about this, currently I've only tried a one-to-many joined view.  There are a couple of aspects in creating the symbology besides date.  First is that the sample has to be set to review = yes in order to be public facing.  I've created a public-facing join of the sample data that is filtering by this field, but I can't create a joined view on the polygon layer using this 'public view' of the sample point data.  The second issue is that sometimes there are two or three sampling locations per pond all done on the same date.  The sample with the highest ranking status (highest concern for Cyanobacteria) will be what needs to be chosen for the symbology of the pond.  This was all previously handled in a python code in ArcPro that would rank the samples per pond per day, but it's proving to be a bit trickier to translate to AGOL.

0 Kudos
JosephRhodes2
Occasional Contributor II

Yep, sounds like a job for Python. Feel free to tag me or PM me if you get stuck. My post from 2020 is a bit outdated now that you can schedule tasks in Notebooks (no need to have a computer always on, or use a third-party cloud environment).

0 Kudos