I have this expression rule :
a!localVariables( /* Loop checks against passed in value of type to pull values from specific requirementActivity match */ a!forEach( items: ri!requirement.requirementActivities, expression: if(contains(fv!item.type, ri!activityType), 'type!{urn:com:appian:types:UW}UW-Requirement-Activity'( key: fv!item.key, type: fv!item.type, creatorId: fv!item.creatorId, creatorFullName: fv!item.creatorFullName, createdDate: fv!item.createdDate, commentText: fv!item.commentText ), {}), ), ),
And I'm using it in my interface :
a!localVariables( requirementsResponse: rule!UW_GetRequirementsByCase_RDS("SomeKey"), local!requirements: { a!forEach( items: local!requirementsResponse, expression: a!map( type: fv!item.name, status:fv!item.status, orderDate: fv!item.createdTimestamp, orderRep: fv!item.requestedBy, receiveDate: rule!UW_GetRequirementActivityByType(fv!item, "RECEIVED").createdDate, receiveRep: rule!UW_GetRequirementActivityByType(fv!item, "RECEIVED").creatorFullName, resolveDate: rule!UW_GetRequirementActivityByType(fv!item, or("WITHDRAWN", "ACCEPTED")).createdDate, resolveRep: rule!UW_GetRequirementActivityByType(fv!item, or("WITHDRAWN", "ACCEPTED")).creatorFullName, resolutionStatus: rule!UW_GetRequirementActivityByType(fv!item, or("ACCEPTED", "WITHDRAWN")).type, resolutionNotes: rule!UW_GetRequirementActivityByType(fv!item, or("ACCEPTED", "WITHDRAWN")).commentText ) ) },
Which I'm using to help populate fields. Everything works great until I save close out and go back...
Then I end up with this error: "Could not display interface. Please check definition and inputs. Interface Definition: Expression evaluation error at function a!forEach [line 6]: Error in a!forEach() expression during iteration 11: Expression evaluation error at function a!map parameter 7 [line 16]: Invalid index: Cannot index property 'createdDate' of type Text into type List of Variant"
Which is pointing to : resolveDate: rule!UW_GetRequirementActivityByType(fv!item, or("WITHDRAWN", "ACCEPTED")).createdDate,
It's not a fan of how I am using the or function - if I remove it and just pass one of the options all is fine. However I only want these fields populated if one or the other value is found. Is there another way to do this? I feel like this should work and again it does but then it does not.
Discussion posts and replies are publicly visible
I would strongly suggest steering clear of using dot notation when you want to get information from somewhere. My general rule of thumb is:
Dot notation doesn't have inbuilt handling of when the field doesn't exist. When you use the function rule!UW_GetRequirementActivityByType(fv!item, or("WITHDRAWN", "ACCEPTED")).createdDate, you are saying "give me the createdDate field please" and dot notation can't handle if the field doesn't exist.
Using the index() or poperty() functions on the other hand, such as property(rule!UW_GetRequirementActivityByType(fv!item, or("WITHDRAWN", "ACCEPTED")), "createdDate", null) says "give the createdDate field please, and if it doesn't exist give me null".
So I suspect it has nothing much to do with your or() (although it could, I'll be honest, I didn't go through your code!).
If this doesn't solve your issue I'll take a deeper look.
EDIT: I have some further feedback
a!localVariables( local!requirementsResponse: rule!UW_GetRequirementsByCase_RDS( inputOne: "SomeKey" ), local!requirements: { a!forEach( items: local!requirementsResponse, expression: a!localVariables( local!receivedRequirementActivity: rule!UW_GetRequirementActivityByType( inputOne: fv!item, inputTwo: "RECEIVED" ), local!withdrawnOrAcceptedRequirementActivity: rule!UW_GetRequirementActivityByType( inputOne: fv!item, inputTwo: { "WITHDRAWN", "ACCEPTED" } ), a!map( type: property( fv!item, "name", {} ), status: property( fv!item, "status", {} ), orderDate: property( fv!item, "createdTimestamp", {} ), orderRep: property( fv!item, "requestedBy", {} ), receiveDate: property( local!receivedRequirementActivity, "createdDate", {} ), receiveRep: property( local!receivedRequirementActivity, "creatorFullName", {} ), resolveDate: property( local!withdrawnOrAcceptedRequirementActivity, "createdDate", {} ), resolveRep: property( local!withdrawnOrAcceptedRequirementActivity, "creatorFullName", {} ), resolutionStatus: property( local!withdrawnOrAcceptedRequirementActivity, "type", {} ), resolutionNotes: property( local!withdrawnOrAcceptedRequirementActivity, "commentText", {} ) ) ) ) },
I really appreciate your response! Very educational and detailed thank you so much.
I will say that implementing your suggested solution unfortunately is not working when passing in 2 activityTypes - I'm not getting any errors which is great but I'm not getting data either.
local!withdrawnOrAcceptedRequirementActivity: rule!UW_GetRequirementActivityByType( requirement: fv!item, activityType: { "WITHDRAWN", "ACCEPTED" } ),
local!requirements: { a!forEach( items: local!requirementsResponse, expression: a!localVariables( local!receivedRequirementActivity: rule!UW_GetRequirementActivityByType( requirement: fv!item, activityType: "RECEIVED" ), local!withdrawnOrAcceptedRequirementActivity: rule!UW_GetRequirementActivityByType( requirement: fv!item, activityType: { "WITHDRAWN", "ACCEPTED" } ), a!map( type: property( fv!item, "name", {} ), status: property( fv!item, "status", {} ), orderDate: property( fv!item, "createdTimestamp", {} ), orderRep: property( fv!item, "requestedBy", {} ), receiveDate: property( local!receivedRequirementActivity, "createdDate", {} ), receiveRep: property( local!receivedRequirementActivity, "creatorFullName", {} ), resolveDate: property( local!withdrawnOrAcceptedRequirementActivity, "createdDate", {} ), resolveRep: property( local!withdrawnOrAcceptedRequirementActivity, "creatorFullName", {} ), resolutionStatus: property( local!withdrawnOrAcceptedRequirementActivity, "type", {} ), resolutionNotes: property( local!withdrawnOrAcceptedRequirementActivity, "commentText", {} ) ) ) ) },
Note that since you posted the same thing twice for some reason, you have some other responses waiting for you in the other posting.
I'll also note that if you're still using similar logic in your expression rule as you posted originally, your contains() call is written backwards; the array of values should come first followed by the value you're checking whether that array contains.
I apologize if my posting in two spots is an issue. Happy to make note on the other. I am new to appian clearly and learning the ropes. I appreciate the response here. Thank you.
I would not recommend deleting the other one. At best, create a comment (or edit the original if possible) with a link pointing to this one if you want this one to be the main one. Deleting it would erase the contributions already made by other responders.
Already done. Thank you again.
"fv!item" is by definition one of the array elements that a!forEach() was called upon, and thus fv!item.type would be a single element. If you've taken Chris's advice and converted ri!activityType to an array of text in which you will pass in all allowable text types, then this is the array. Per the documentation for contains(), the array is passed first and the value you're looking for is passed second:
Edit: by the time I finished writing this, the comment I was replying to has disappeared. Hopefully that means you figured out this issue already?
Ah! I just needed to update the rule input to array for activityType - got it - all is well Thank you Mike Schmitt and especially thank you again ajhick for your clear and thorough response. Very grateful for the help.