Calcs and Setting Values in an Accordion

Dan Rosenstein:
What’s the syntax for setting a key in an accordion\listrows via a function? I thought that ‘model.keyname==newvalue’ references the model inside the accordion (ie equivalent to ‘model.array[x].keyname’==newvalue’)


Christina Saran:
assign is one equal =. Does this help?


Dan Rosenstein:
You are right of course. Unfortunately it was a typo


Dan Rosenstein:
I tried: model.CampersInfo[0].Cheque.url=‘xxxx’;


Dan Rosenstein:
model.Cheque==‘xxx’


Dan Rosenstein:
this.model.Cheque=‘xxxx’


Dan Rosenstein:
etc


Dan Rosenstein:
the first works but of course it only references the first item


Andrew Dam:
I think functions are ran in the context of the window, which is why I did the whole _.findIndex using the accordion generated bfId and match the index that way. You can see a reference of that in the named action for the uploadcare example I shared before.


Dan Rosenstein:
I think Charles once figured it out using something like this example: jp.paths(this.model, ‘$.CamperInfo[?(@.Description)]’).length


Dan Rosenstein:
unfortunately that doesnt seem to work now and also it is maybe good for checking validity but not setting values.


Dan Rosenstein:
but looking at some old forms I have they do seem to follow the model.keyname syntax. But maybe that broke in the newer builds.


Dan Rosenstein:
so a parent is registering kids for camp. Needs to upload 2 files per child. I need to be able to detect if they uploaded and if so then to show a clear button and file name etc.


Christina Saran:
okay, does the jp.paths give a console error


Dan Rosenstein:
I’m not an expert on the console unfortunately. Would the JP function be able to set a value if it worked?


Dan Rosenstein:
the form actually doesnt load: ERROR
10201
SyntaxError: unexpected token: ‘]’
Failed to compile *_calc or *_calcf: jp.value(this.model, ‘$.Requested[?(@.HFcamperName’)]’).length


Dan Rosenstein:
this does come up: “visible_calc”: “jp.paths(this.model, ‘$.CampersInfo[?(@.HFcamperName)]’).length” but doesn’t seem to do anything


Christina Saran:
ok if its not clear what that was used for then, Andrew’s direction was fantastic.


Dan Rosenstein:
it was used for visible_calc - never tried it for setting values. Don’t know if that’s possible


Andrew Dam:
Maybe, if it’s for a visible_calc then it does sound tricky


Andrew Dam:
Let me give it a shot and I’ll get back to you


Dan Rosenstein:
:+1:


Dan Rosenstein:
are we sure that referencing a key inside an object doesn’t work? ie model.keyname=newvalue


Andrew Dam:
Ok, I changed the visible_calc to:

"visible_calc": "_.findIndex(model.files, function(o) { return 'PhotoID' in o &amp;&amp; o.PhotoID.isUploaded == 1; }) < 0; "

which checks if the PhotoID object exists in the object, and if isUploaded is set to 1. isUploaded gets set in the namedAction after a successful upload.

I modified the existing example if you would like to take a look.


Dan Rosenstein:
Great! how can I set the value there?


Dan Rosenstein:
(ie ‘clear button’)


Dan Rosenstein:
add a =value instead of the <0 ?


Dan Rosenstein:
in a function


Andrew Dam:
Can you detail the desired result? A clear button that clears the file uploaded? Will there be a clear button for each button in the accordion?


Dan Rosenstein:
so if someone uploads the wrong file and wants to clear. So clear the ‘PhotoID’ or cheque


Andrew Dam:
HTML blocks actually have context of the accordion row they’re in, so you could create an HTML button and do it in an @click.


Dan Rosenstein:
true - I guess I can take your upload button and modify it to clear content instead of inserting uploadcare data - if my JS skills can manage that


Andrew Dam:
Can take another look at the example, added a Clear button that clears the PhotoID, though since the fileName and url existed, they just show up as ‘no file uploaded’. Not sure how you’re presenting that information but you can modify it to how you need.


Dan Rosenstein:
Great! something not quite right with the clear of the cheque, but I can probably figure it out


Dan Rosenstein:
Cheers Andrew - good stuff


Dan Rosenstein:
almost there, but can’t get the validator for the file to work. Can I not use the same logic in a validator_calc?


Dan Rosenstein:
ie


Dan Rosenstein:
“required”: true,
“Validator”:“calc”,
“validator_calc”:"_.findIndex(model.CampersInfo, function(o) { return ‘CamperPicture’ in o && o.CamperPicture.isUploaded == 1; }) == 0; ",
“errorMsg”: “please upload the document”


Dan Rosenstein:
(the logic returns the correct true or false in a label_calc)


Andrew Dam:
_.findIndex() will return a -1 if it doesn’t find it in the function, else returns the index of the row in the accordion.


Dan Rosenstein:
but the validator seems to ignore result


Andrew Dam:
oh, perhaps capital V in "Validator":"calc" should be a lower case


Dan Rosenstein:
ah! maybe


Dan Rosenstein:
getting hard to see


Dan Rosenstein:
was so close :slightly_smiling_face: yes you got it!


Andrew Dam:
Awesome, glad you got it working.


Dan Rosenstein:
:+1:


Update:

Using a _calc in an accordion is difficult, and the previous example did not work correctly. EDIT: See Update 3

For the visible_calc, we can use a v-if on the button instead:

v-if="!model?.PhotoID?.isUploaded"

This method takes advantage of Optional Chaining to test for the existence of a nested key. In this case, since PhotoID doesn’t exist until a file was uploaded, we can’t directly check for isUploaded. Using Optional Chaining prevents an error from occurring from referencing an undefined key.

While this addresses the need to hide buttons after an upload, it still doesn’t solve the overarching issue of using a _calc in an accordion, and presents an issue when using validator_calc. EDIT: See Update 2

You could instead run a named action similar to uploadFile that passes the bfId to check if the necessary keys exist. It doesn’t fit into the regular validation routine, but rather a workaround. If all the accordion rows need to be filled out, then you can still use a validator_calc by checking every object in the array for a certain key.

"validator_calc": "_.findIndex(model.files, function(o) { return !('PhotoID' in o) || o?.PhotoID?.isUploaded == 0 || !('Cheque' in o) || o?.Cheque?.isUploaded == 0}) == -1;"

This checks every accordion row to see if they’re missing a file upload. If they are, the calculation returns a number greater than -1 and the validator fails. If the validator cannot find a missing file, then it returns -1 and the validator passes.

I will update this post if a better solution arises.

Update 2:

Turns out the validator_calc does calculate in the context of the accordion row.

Update 3:

visible_calc can get context of itself using this.model. The example has been updated with this implementation rather than v-if.