Hi,
I have editable grid having two columns one is readonly field for showing label and in the second column the user will enter the data. The data for this columns is getting from a local variable . The user can delete the rows and he add row upto 5 rows.
Now I have a cdt with fields like r1, r2, r3, r4, r5. Now I want to map the data entered by the user to cdt.
Discussion posts and replies are publicly visible
This is a fairly straightforward case for an editable grid. If you're using 17.2 or above, you can also do it without even needing to declare a sub-rule (at least for starters). See below example.
load( local!data: { { id: 1, label: "r1", value: "" }, { id: 2, label: "r2", value: "" } }, a!sectionLayout( label: "Test Editable Grid", contents: { a!paragraphField( label: "DEBUG", showWhen: false(), value: local!data, disabled: true() ), a!gridLayout( headerCells: { a!gridLayoutHeaderCell(label: "Label"), a!gridLayoutHeaderCell(label: "Value") }, rows: a!forEach( local!data, a!gridRowLayout( contents: { a!textField( value: fv!item.label, readOnly: true() ), a!textField( value: fv!item.value, saveInto: fv!item.value ) } ) ), addRowLink: if( length(local!data) < 5, a!dynamicLink( label: "Add Row", saveInto: a!save( local!data, append( local!data, { id: max(local!data.id)+1, label: "r" & max(local!data.id)+1, value: null() } ) ) ), null() ) ) } ) )
My requirement is to create dynamic sections with grid layout based on the dropdown selection.Columns in grid:- Question(Read Only)- Order No (Editable) - On load ,the order no field is disabled.Once the row is selected, the order no field will be enabled and the value will be saved in cdt variable.
I am facing issues when saving the order no values into cdt. Each row's order number field value overwrites when other row is selected.
Thanks in advance!
Interesting use case. Some follow-up questions from me:
Hi Mike,
Thanks for your reply. Please find the answers below:
Thanks for your reply - before I dig into your code I have a suggestion/request - maybe you could edit your post and put your sample code in a Code box - use the "insert" tool on the toolbar of the editor then choose "insert code", and paste your code there instead - that allows it to maintain formatting as well as not extending your comment window to extreme lengths. Thanks!
load( local!selectedSections: { { "sectionId": 1, "sectionName": "Section1" }, { "sectionId": 2, "sectionName": "Section2" } }, local!selectedSectionQuestions: { { "pId": 1, "question": "e1", "orderNo": null, "refSectionId": 1 }, { "pId": 2, "question": "e2", "orderNo": null, "refSectionId": 1 }, { "pId": 3, "question": "p1", "orderNo": null, "refSectionId": 2 }, { "pId": 4, "question": "p2", "orderNo": null, "refSectionId": 2 }, { "pId": 5, "question": "p3", "orderNo": null, "refSectionId": 2 } }, local!selectedQuestions:type!question_cdt(), with( {a!forEach( items: local!selectedSections, expression: rule!TEST_uiDisplayQuestion( questions: local!selectedSectionQuestions, showWhen: 1, sections: fv!item, selectedSectionQuestions: local!selectedQuestions ) )} ) ) -------------- TEST_uiDisplayQuestion load( local!questions: index( ri!questions, wherecontains( tointeger( ri!sections.sectionId ), tointeger( ri!questions.refSectionId ) ), {} ), local!sequence: a!forEach( items: local!questions, expression: null ), local!selectedIndices: tointeger( {} ), { a!sectionLayout( label: ri!sections.sectionName, contents: { a!gridLayout( label: "", headerCells: { a!gridLayoutHeaderCell( label: "Available Questions" ), a!gridLayoutHeaderCell( label: "Order No" ) }, columnConfigs: { a!gridLayoutColumnConfig( width: "DISTRIBUTE", weight: 1 ), a!gridLayoutColumnConfig( width: "NARROW" ) }, rows: a!forEach( items: local!questions, expression: a!gridRowLayout( id: fv!item.pId, contents: { a!paragraphField( label: "available questions", labelPosition: "ABOVE", value: fv!item.question, readOnly: true ), a!integerField( label: "orderNo", labelPosition: "ABOVE", value: fv!item.orderNo, saveInto: { fv!item.orderNo, local!sequence[fv!index] }, disabled: rule!APN_isBlank( wherecontains( tointeger( fv!item.pId ), tointeger( local!selectedIndices ) ) ), required: if( contains( tointeger( local!selectedIndices ), wherecontains( local!selectedIndices, tointeger( fv!item.pId ) ) ), true, false ) ) } ) ), selectionValue: local!selectedIndices, selectionSaveInto: { local!selectedIndices, a!save( local!selectedIndices, reject( fn!isnull( _ ), save!value ) ), a!forEach( items: local!questions, expression: { a!save( local!sequence[wherecontains( tointeger( fv!item.pId ), tointeger( local!selectedIndices ) )], if( contains( tointeger( local!selectedIndices ), wherecontains( tointeger( fv!item.pId ), tointeger( local!selectedIndices ) ) ), local!sequence[wherecontains( tointeger( fv!item.pId ), tointeger( local!selectedIndices ) )], null ) ) } ), a!save( ri!selectedQuestions, index( local!questions, wherecontains( tointeger( local!selectedIndices ), tointeger( local!questions.pId ) ), {} ) ) }, selectable: true, selectionRequired: true ) } ) } )
Are you saying questions won't have an Order value by default? Why?
BTW, I have reproduced a partially-simplified version of your use case using my own new code. In the case of this sample code it seems to work when I enter order numbers. Please try this out and see if it helps you with your specific implementation.
load( local!groceryList: { { id: 1, name: "Milk", orderNum: null(), category: "Food" }, { id: 2, name: "Tide Pods", orderNum: null(), category: "Cleaning Supplies" }, { id: 3, name: "Eggs", orderNum: null(), category: "Food" }, { id: 4, name: "Paper Towels", orderNum: null(), category: "Cleaning Supplies" } }, local!categories: union(local!grocerylist.category, local!groceryList.category), local!selectedItems: {}, a!sectionLayout( contents: { a!forEach( local!categories, with( local!currentCategory: fv!item, a!gridLayout( label: fv!item, headerCells: { a!gridLayoutHeaderCell(label: "Item"), a!gridLayoutHeaderCell(label: "Order") }, selectable: true(), selectionSaveInto: { local!selectedItems }, selectionValue: local!selectedItems, /*selectionStyle: "ROW_HIGHLIGHT",*/ rows: a!forEach( local!groceryList, if( fv!item.category = local!currentCategory, a!gridRowLayout( id: fv!item.id, contents: { a!richTextDisplayField( label: "Item Name Display", value: a!richTextItem( text: fv!item.name ) ), a!textField( label: "Order Number Editor", value: fv!item.orderNum, saveInto: { fv!item.orderNum }, disabled: not( contains( local!selectedItems, fv!item.id ) ) ) } ), {} ) ) ) ) ), a!boxLayout( label: "DEBUG", style: "INFO", isCollapsible: true(), isInitiallyCollapsed: true(), contents: { a!paragraphField( value: "Selections: " & local!selectedItems & char(10) & "CDT Data: " & local!groceryList ) } ) } ) )
Thanks!I tried the new code but grid selection is not retained when i select multiple sections.
Did you change anything from my example? I have to double check but it seemed to work for me no matter which section I selected items from. What happens wrong exactly? Also can you confirm what Appian version you're on?