How to not use a list item more than once.

358
6
02-27-2019 07:32 AM
DougBrowning
MVP Frequent Contributor

I have a select one list in a repeat where I want to stop, or warn, a user if they pick an item more than once during the repeats.  This list is about 1,300 items.

I created a field that keeps a running list from my repeat

join(", ", ${SpeciesList})

I tried this constraint on the list  not(contains(${AllPlants}, ${SpeciesList}))  but it always triggers since it is in the list as soon as i pick it.

Is there a way to count the number of string occurrences?  Or remove it from the check somehow.

Thanks for any ideas

Tags (3)
0 Kudos
6 Replies
DougBrowning
MVP Frequent Contributor

I got this to kinda work but it has issues.  What I do is take off the last 3 chars of the running list, thus breaking up that last value - which is then not found.

not(contains(substr(${AllPlants}, 0, string-length(${AllPlants}) - 3), ${SpeciesList}))

If you go down the repeat in order this works.  But this falls apart if you go backwards in a repeat and try and change a value.

What would be nice is a count of the number of substrings found.  so substr("XXXXX", "X") returns 5 not just true false.  Or a contains that returns the position the string was found would work also.

Thanks for any ideas.

0 Kudos
EvanR
by
New Contributor II

Trying to implement your solution because I had problems with the JavaScript function. However, the question I'm trying to add this constraint to is a decimal type, which is causing issues. I eventually figured out how to calculate a version of my list of entries with the current entry removed (non-trivial). However, because Survey123 lists appear to be a string type at their core rather than a true list, any subsequent value that matches part of a previous entry will not be allowed. For example, if my list of entries is "1,1.5,3" and I try to enter 5, it won't allow it since 1.5 contains a 5. Any suggestions? All entries will be positive values that are divisible by 0.5.

For reference, here's the complicated formula I came up with that calculates a version of the entries list with the current entry removed: if(string-length(${InterceptList})=string-length(string(${PointDistance_m})),"",substr(${InterceptList},0,string-length(${InterceptList})-string-length(string(${PointDistance_m}))))

${InterceptList} is the raw list and ${PointDistance_m} is the question I'm trying to constrain. Have to coerce values to string, and the if statement was necessary because any time I was making an initial entry it would appear in the list (removal of the current entry only seemed to work for entries after the first).

0 Kudos
EvanR
by
New Contributor II

Think I may have solved it: I calculated a second version of the value in question by multiplying each entry by a constant and use THAT for the list and the duplicate check. I haven't yet tested it fully but it seems to work so far. First tried adding a constant, but that caused problems as well (e.g., if you add 0.3, 200, etc. to 16.5 and to 6.5 the latter will still be a substring of the former).

0 Kudos
AndrewPadilla
New Contributor III

I am looking for this solution as well. I attempted to use JavaScript as described in 

JavaScript funtions in Survey123 (https://community.esri.com/t5/arcgis-survey123-blog/extending-survey123-smart-forms-with-custom-js-f... but was unable to reproduce a working HasDups function in Survey123.  Has anyone else been able to successfully reproduce this example?  The constraint does not seem to register correctly. In the example below any fruits entered are an invalid selection with the constraint (${dups}=false).

AndrewPadilla_1-1614812922297.png

I attached an example file and script:

function HasDups (myArray){

return new Set(myArray).size !== myArray.length;

}

Thanks,

Andy

 

0 Kudos
EvanR
by
New Contributor II

Did you download repeats.js and place it in an "extensions" directory within your survey directory? You have to do that before you can call the script from your XLSForm. I was able to get it to work in Survey123 Connect once I figured out that step, but it didn't work when deployed to field tablets because of some restrictions on what exact flavors of AGOL etc. allow JavaScript, which was a bummer.

See here and also here. Let me know if that doesn't work for you and I'll take a closer look.

0 Kudos
AndrewPadilla
New Contributor III

Thanks for your response @EvanR. Yes, I should have mentioned, I had placed 'myFunctions.js' in a scripts folder (I believe the extensions folder works the same). In the end I did get it to work. It was as simple as placing quotation marks around false in my constraint. I have attached a revised working example. JavaScript files cannot be added here. One would need to create a 'myFunctions.js' and use the following function and place it in a scripts folder with in the survey folder: 

function HasDups (myArray){

return new Set(myArray).size !== myArray.length;

}

 

0 Kudos