HI guys
I'm chasing my tail here.
We are assessing software against 4 criteria per software title.
For each criterion we have a different assessor group.
The software titles are kept in a list of map since they are not yet approved for our Allow List and we don't want to keep the data if they are not approved.
We have a custom comments record type which has a many-to-one relationship with the software table.
Issue:
For each software title we need to keep 4 comments, but I find I am only able to overwrite the comments value, not append.Here's the code for my approval details interface:
a!localVariables( local!softwareCategoryList: rule!getSoftwareCategoryList( includeDisabled: false, includedSoftwareCategoryID: if( a!isNullOrEmpty( ri!mappedValue.software[Global Software.fields.id'] ), null, ri!mappedValue.software['recordType!Global Software.fields.softwareCategoryID'] ) ), a!gridLayout( label: "Approve Software", labelPosition: "COLLAPSED", headerCells: { a!gridLayoutHeaderCell(label: "Software Name"), a!gridLayoutHeaderCell(label: "Category Name"), a!gridLayoutHeaderCell(label: "Vendor Name"), a!gridLayoutHeaderCell( label: "", showWhen: and(not(ri!readOnly), not(ri!edit)) ), a!gridLayoutHeaderCell( label: "Comment", showWhen: rule!APP_isTrue(ri!mappedValue.decision), align: "LEFT" ), a!gridLayoutHeaderCell( label: "Status", showWhen: and(ri!readOnly, not(ri!edit)) ) }, columnConfigs: { a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 3), a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 3), a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 3), a!gridLayoutColumnConfig(width: "NARROW", weight: null), a!gridLayoutColumnConfig(width: "MEDIUM"), a!gridLayoutColumnConfig(width: "DISTRIBUTE") }, rows: a!forEach( items: ri!mappedValue, expression: { a!gridRowLayout( id: fv!index, contents: { a!textField( label: "Software Name", labelPosition: "COLLAPSED", value: fv!item.software['recordType!Global Software.fields.name'], saveInto: fv!item.software['recordType!Global Software.fields.name'], readOnly: or(ri!readOnly, not(ri!edit)) ), a!richTextDisplayField( label: "Category Name", labelPosition: "ADJACENT", value: { a!richTextItem( text: fv!item.software['recordType! Global Software.relationships.softwareCategory.fields.name'] ), char(32), a!richTextIcon( icon: "question-circle-o", caption: fv!item.software['recordType!Global Software.relationships.softwareCategory.fields.description'], showWhen: a!isNotNullOrEmpty( fv!item.software['recordType!Global Software.relationships.softwareCategory.fields.description'] ), color: "#b3d1e6", size: "MEDIUM" ) }, showWhen: or(ri!readOnly, not(ri!edit)) ), a!dropdownField( choiceLabels: local!softwareCategoryList['recordType!Software Category.fields.name'], choiceValues: local!softwareCategoryList['recordType!Software Category.fields.id'], label: "Software Category", labelPosition: "ADJACENT", placeholder: "--- Select a software category ---", value: fv!item.software['recordType!Global Software.fields.softwareCategoryID'], saveInto: { fv!item.software['recordType!Global Software.fields.softwareCategoryID'], a!save( fv!item.software['recordType! Global Software.relationships.softwareCategory'], index( local!softwareCategoryList, wherecontains( save!value, local!softwareCategoryList['recordType!Software Category.fields.id'] ), null ) ) }, showWhen: and(not(ri!readOnly), (ri!edit)), required: true ), a!textField( label: "Vendor Name", labelPosition: "COLLAPSED", value: fv!item.software['recordType!Global Software.fields.vendorName'], saveInto: fv!item.software['recordType!Global Software.fields.vendorName'], readOnly: or(ri!readOnly, not(ri!edit)) ), a!radioButtonField( choiceLabels: { "Approve", "Rejected" }, choiceValues: { true, false }, label: "Approve", labelPosition: "COLLAPSED", value: fv!item.decision, saveInto: { fv!item.decision }, showWhen: and(not(ri!readOnly), not(ri!edit)), required: true, choiceLayout: "COMPACT", choiceStyle: "CARDS" ), a!paragraphField( label: "Comments", labelPosition: "ABOVE", placeholder: "Please add any comments you may have", value: ri!mappedValue.software['recordType!Global Software.relationships.comments.fields.comment'], saveInto: { ri!mappedValue.software['recordType!Global Software.relationships.comments.fields.comment'] }, refreshAfter: "UNFOCUS", height: "MEDIUM", showWhen: rule!APP_isTrue(ri!mappedValue.decision), readOnly: rule!APP_isTrue(ri!readOnly), disabled: false ), a!tagField( labelPosition: "COLLAPSED", tags: { a!match( value: true, equals: fv!item.decision, then: a!tagItem( text: "APPROVED", backgroundColor: "#0c9aba" ), default: a!tagItem( text: "NOT APPROVED", backgroundColor: "#FF9B78" ) ) }, showWhen: and(ri!readOnly, not(ri!edit)) ) }, selectionDisabled: false ) } ), selectionSaveInto: {}, allowRowReordering: false, validations: {}, shadeAlternateRows: false, borderStyle: "LIGHT" ) )
I know there's probably a simple answer but I am drowning in a lake of overthink!Any help will be gratefully accepted
Blessings
Stephen
Discussion posts and replies are publicly visible
Keep in mind that grids aren't a great UX to edit a 1:many relationship within a given row directly. You'll probably want a drilldown UX pattern. The grid would simply show the comments with the link to edit the list of comments in a sidebar (or similar).
To demonstrate this, try the following:
This line:saveInto: { ri!mappedValue.software['recordType!Global Software.relationships.comments.fields.comment'] },
saveInto: { ri!mappedValue.software['recordType!Global Software.relationships.comments.fields.comment'] },
Would turn into something like:
saveInto: { a!save( ri!mappedValue.software['recordType!Global Software.relationships.comments'], append( ri!mappedValue.software['recordType!Global Software.relationships.comments'], recordType!Comment(comment: save!value) ) ) },
There's probably a bit more needed to handle null values, but that's the gist.