Hi Community,
How can i make checkbox visible/hidden based on previous DropDown value.
For ex - I have dropdown field as Product having values - KFC, Pizzahut.
I have different checkboxes values if user selects KFC or Pizzahut.
How can i show different checbox dynamically after user selects dropdwon value.
I don't want to show all checkbox value and then hide. Based on the choice KFC/Pizzahut corresponding Checkbox options should dynamically come in form.
Here is the code that i am trying. Please help me with this.
if( ri!readOnly, a!textField( label: "Product", labelPosition: "ADJACENT", value: ri!record.productGroupAffected.value, readOnly: true ), a!dropdownField( label: "Product", labelPosition: "ABOVE", instructions: "", helpTooltip: "", placeholderLabel: "--- Select a Value ---", choiceLabels: local!productGroupAffectedOptions.value, choiceValues: local!productGroupAffectedOptions, value: ri!record.productGroupAffected, saveInto: ri!record.productGroupAffected, required: false ) ), if( ri!record.productGroupAffected = "KFC", a!textField( label: "Tools Affected KFC", labelPosition: "ADJACENT", value: if( or(isnull(ri!record.toolsAffected), count(ri!record.toolsAffected.value)=0), "", joinarray(ri!record.toolsAffected.value, ", ") ), readOnly: true ), a!checkboxField( label: "Tools Affected KFC", labelPosition: "ABOVE", instructions: "", helpTooltip: "", choiceLabels: local!checkbox1Value, choiceValues: local!checkbox1Value, value: ri!record.toolsAffected, saveInto: ri!record.toolsAffected, required: false ) ), if( ri!record.productGroupAffected = "PizzaHut", a!textField( label: "Tools Affected PizzaHut", labelPosition: "ADJACENT", value: if( or(isnull(ri!record.toolsAffected), count(ri!record.toolsAffected.value)=0), "", joinarray(ri!record.toolsAffected.value, ", ") ), readOnly: true ), a!checkboxField( label: "Tools Affected PizzaHut", labelPosition: "ABOVE", instructions: "", helpTooltip: "", choiceLabels: local!checkbox2Value, choiceValues: local!checkbox2Value, value: ri!record.toolsAffected, saveInto: ri!record.toolsAffected, required: false ) ),
Discussion posts and replies are publicly visible
Hi Thank you for your help. Here are the details -
Something like the below attached screenshot i am trying to achieve on my interface -
Where Product Group Affected has a dropdown value coming from constant, Tools affected values are coming from an expression rule based on Product Group affected selection and finally foreach() loop for Nodes Affected for each Tool. But Nodes Affected checkbox selections are not working for me. Below is the code for it which i am using by replacing local variables with rule input.
a!dropdownField( label: "Product Group Affected", labelPosition: "ABOVE", placeholderLabel: "--- Select a Value ---", choiceLabels: cons!CCCProductGroupAffectedOptions, choiceValues: cons!CCCProductGroupAffectedOptions, value: ri!CCC.ProductGroupAffected, saveInto: { ri!CCC.ProductGroupAffected, /* the below will clear the previous Tools Affected Selection when the Product Group Affected is changed */ a!save( ri!CCC.ToolsAffected, {} ) }, validations: {} ), a!checkboxField( label: "Tools Affected", labelPosition: "ABOVE", choiceLabels: rule!CCCToolsAffectedOptions(ri!CCC.ProductGroupAffected), choiceValues: rule!CCCToolsAffectedOptions(ri!CCC.ProductGroupAffected), value: ri!CCC.ToolsAffected, saveinto: ri!CCC.ToolsAffected, /*ChoiceLayout: "COMPACT",/*STACKED*/ showwhen: not(isnull(ri!CCC.ProductGroupAffected)), validations: {} ), a!columnsLayout( columns: a!forEach( ri!CCC.ToolsAffected, with( local!currentIndex: wherecontains( fv!item, touniformstring(property(ri!CCC.NodesAffected, "Tool", {})) ), a!columnLayout( contents: { a!checkboxField( label: "Nodes Affected for : '" & fv!item & "'", labelPosition: "ABOVE", /*instructions: "current index: " & local!currentIndex,*/ choiceLabels: cons!CCCNodesAffectedOptions, choiceValues: cons!CCCNodesAffectedOptions, value: tointeger( property( index( ri!CCC.NodesAffected, local!currentIndex, null() ), "Nodes", null() ) ), saveInto: { a!save( ri!CCC.NodesAffected, append( if(isnull(local!currentIndex), ri!CCC.NodesAffected, remove(ri!CCC.NodesAffected, local!currentIndex) ), if( rule!APN_isEmpty(save!value), /* indicates all size choices have been de-selected, so we'll save an empty set here to remove this menu choice from the saved data set */ {}, { Tool: fv!item, Nodes: save!value } ) ) ) } ) } ) ) ), showwhen: not(isnull(ri!CCC.ProductGroupAffected)) ),
I am using a interface input named CCC of type CDT. To get the checkbox values Tools Affected and Nodes Affected i have made as an Array.
Let me know if you need any other information. I tried a lot to debug the issue but wasn't able to figure out and looking for help.
prais1852 First of all, migrating from Higher Version to Lower version is never a good approach. Because this require lot of changes to be done in your application. Now coming back to your requirement, there are no alternative for a!columnsLayout(). Till 17.1 version, we had max 2 columns for each UI, while UI designing, whereas from 17.2 on-wards a!columnsLayout() added more flexibility to have multiple columns as per our need. So, if you have switched from 17.2 to 17.1, i recommend change your layouts and their contents. And also replace all those functions which are introduced in 17.2 with their similar one in 17.1 as already been discussed above
If i would like to go with saving in JSON string. How can i do that ? Can you share some links for help if possible ? I am really scared of dealing with Nested CDTs, Managin CDTs is tough for me.
Since I'm feeling generous, I went back to my old example and converted it to be able to store its saved values in a new CDT containing fields pretty much exactly like yours:
I'm doing the JSON conversion like I referenced in my prior reply - notice that I created a new WITH variable which checks whether there's any value in the "Size" array (in your version that would be "NodesAffected"), and if so, translates each one back from a JSON string to dictionary data (like was originally used in my original version); then in the checkbox field, it uses this local variable for display, but saves directly into ri!menuSelectionCdt.Size (converting the saved values into a JSON string prior to storing them in the text varray). You should be able to translate this pretty much directly into your use case.
load( local!restaurantChoices: { {id: 1, name: "KFC"}, {id: 2, name: "Pizza Hut"} }, local!selectedRestaurant, local!menuSelection: {}, /*local!menuSelectionSizes: {},*/ with( /* dynamically set the menu choices based on which restaurant is picked */ local!menuChoices: if( isnull(ri!menuSelectionCdt.RestaurantSelected), {}, if( tointeger(ri!menuSelectionCdt.RestaurantSelected) = 1, { "Fried Chicken", "Mashed Potatoes", "Cole Slaw", "Biscuits", "Gravy" }, if( tointeger(ri!menuSelectionCdt.RestaurantSelected) = 2, { "Pizza", "Bread Sticks", "Salad Bar", "Soft Drinks" }, {} ) ) ), /* set up Menu Selection Sizes to be an array of dictionary - the format will resemble this: { item: "item name", size: {sizeIds} } */ /* NEW: so we can store these selections safely in a TEXT cdt value, we will convert them to JSON strings for storage in the CDT, and back into dictionary data for use in the form. */ local!menuSelectionSizes: if( apn_isEmpty(ri!menuSelectionCdt.Size), {}, apply( /* since there will be a separate JSON string for each menu selection */ a!fromJson, ri!menuSelectionCdt.Size ) ), a!formLayout( /* now assuming 17.2 or newer */ contents: { a!radioButtonField( label: "Chain:", labelPosition: "ADJACENT", choiceLabels: local!restaurantChoices.name, choiceValues: local!restaurantChoices.id, value: ri!menuSelectionCdt.RestaurantSelected, saveInto: { ri!menuSelectionCdt.RestaurantSelected, /* the below will clear the previous menu selection when the restaurant is changed */ a!save( ri!menuSelectionCdt.MenuSelections, {} ) } ), if( not(isnull(ri!menuSelectionCdt.RestaurantSelected)), a!checkBoxField( label: "Make your food choices:", labelPosition: "ADJACENT", choiceLabels: local!menuChoices, choiceValues: local!menuChoices, value: ri!menuSelectionCdt.MenuSelections, saveInto: { a!save( ri!menuSelectionCdt.MenuSelections, /* this weird saveInto style will attempt to keep the saved value array in the same order as the initial checkboxes, since Appian versions 17.1 and later no longer do this automatically */ index( local!menuChoices, whereContains( save!value, local!menuChoices ) ) ) } ), {} ), a!columnsLayout( columns: a!forEach( ri!menuSelectionCdt.MenuSelections, with( local!currentIndex: wherecontains( fv!item, touniformstring(property(local!menuSelectionSizes, "item", {})) ), a!columnLayout( contents: { a!checkboxField( label: "Select Size: '" & fv!item & "'", labelPosition: "ABOVE", choiceLabels: {"Small", "Medium", "Large"}, choiceValues: {1, 2, 3}, value: tointeger( property( index( local!menuSelectionSizes, local!currentIndex, null() ), "sizes", null() ) ), saveInto: { a!save( ri!menuSelectionCdt.Size, append( if( isnull(local!currentIndex), ri!menuSelectionCdt.Size, remove(ri!menuSelectionCdt.Size, local!currentIndex) ), if( apn_isEmpty(save!value), /* indicates all size choices have been de-selected, so we'll save an empty set here to remove this menu choice from the saved data set */ a!toJson({}), a!toJson( { item: fv!item, sizes: save!value } ) ) ) ) } ) } ) ) ) ), a!paragraphField( label: "(debug info)", value: "Menu Selection Size choices converted back from JSON: " & char(10) & local!menuSelectionSizes ), {} } ) ) )