RuleInput, multidropdown

a!localVariables(
  local!lineOfBusiness: rule!LCM_getLineOfBusinesses(lobkey: null(), lobcode: null()),
  local!attorneys: rule!LCM_getAttorneys(soeid: null(), attorneykey: null()),
  local!selectedAttorney,
  local!selectedAttorneyLOB,
  local!attorneyLOB: { a!map(attorneykey: null(), lobkey: null()) },
  a!formLayout(
    label: "Form",
    contents: {
      a!boxLayout(
        label: "Attorney - Line of Businesses",
        contents: {
          a!gridLayout(
            label: "",
            labelPosition: "ABOVE",
            totalCount: count(local!attorneyLOB),
            headerCells: {
              a!gridLayoutHeaderCell(label: "Attorney(s)"),
              a!gridLayoutHeaderCell(label: "Line of Business"),
              a!gridLayoutHeaderCell(label: "")
            },
            columnConfigs: {
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 1),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 1),
              a!gridLayoutColumnConfig(width: "ICON")
            },
            rows: {
              a!forEach(
                items: local!attorneyLOB,
                expression: a!gridRowLayout(
                  contents: {
                    a!dropdownField(
                      label: "Attorney(s)" & fv!index,
                      labelPosition: "ABOVE",
                      helpTooltip: "Attorney(s)",
                      placeholder: "Select a Attorney",
                      choiceLabels: index(local!attorneys, "name", ""),
                      choiceValues: index(local!attorneys, "attorneykey", ""),
                      value: fv!item.attorneykey,
                      saveInto: 
                      {
                        fv!item.attorneykey,
                        a!save(
                          target: ri!intakeattorneys,
                          value: a!forEach(
                            items: local!attorneyLOB,
                            expression: {AttorneyKey: fv!item.attorneykey}
                          )
                         )
                       },
                      required: true
                    ),
                    a!multipleDropdownField(
                      label: "LOB" & fv!index,
                      labelPosition: "ABOVE",
                      placeholder: "Select a Line of Business",
                      choiceLabels: index(local!lineOfBusiness, "lobname", ""),
                      choiceValues: index(local!lineOfBusiness, "lobkey", ""),
                      value: fv!item.lobkey,
                      saveInto: {fv!item.lobkey,
                      
                      a!save(
                        ri!attorneyLineOfBusiness,
                        value: a!forEach(
                          items: local!attorneyLOB,
                          expression: {attorneykey: fv!item.attorneykey, 
                          lobkey: 
                          a!forEach(
                          items: fv!item.lobkey,
                          expression: {lobkey: fv!item}
                          )
                          }
                        )
                      )
                      },
                      required: true
                    ),
                    a!imageField(
                      label: "delete " & fv!index,
                      images: a!documentImage(
                        document: a!iconIndicator("REMOVE"),
                        altText: "Remove",
                        caption: "Remove ",
                        link: a!dynamicLink(
                          value: fv!index,
                          saveInto: {
                            a!save(
                              local!attorneyLOB,
                              remove(local!attorneyLOB, save!value)
                            )
                          },
                          
                        ),
                        showWhen: fv!index > 1
                      ),
                      size: "ICON"
                    )
                  }
                )
              )
            },
            selectionSaveInto: {},
            validations: {},
            shadeAlternateRows: true,
            addRowLink: a!dynamicLink(
              label: "Add",
              saveInto: {
                a!save(
                  local!attorneyLOB,
                  append(local!attorneyLOB, save!value)
                )
              }
            ),
            rowHeader: 1
          )
        },
        style: "STANDARD",
        marginBelow: "STANDARD"
      )
    },
    buttons: a!buttonLayout(
      primaryButtons: {
        a!buttonWidget(
          label: "Submit",
          submit: true,
          style: "PRIMARY"
        )
      },
      secondaryButtons: {
        a!buttonWidget(
          label: "Cancel",
          value: true,
          saveInto: ri!cancel,
          submit: true,
          style: "NORMAL",
          validate: false
        )
      }
    )
  )
)
Hi,

I have a user input with editable grid where each row will have 2 dropdowns.

The first dropdown "Attorney(s)" is a single selection where as "Line of Business" is a multiselection.

I have able to save the attorneykey to the rule input (black arrow in the image), where as I was unable to save/pass lobkey (multiple values) into the rule input.

Can someone give an idea who can I fix this. Thanks in advance.

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer

    What is the CDT definition for the "attourneyLineOfBusiness" rule input?  Is the "lobkey" property single or multiple?

    It looks like every time the multiple dropdown is changed (regardless of the row) you're attempting to overwrite the value of "ri!attourneyLineOfBusiness" with a copy stored in the local!attourneyLOB dictionary where the "lobkey" property is actually multiple values.  If your CDT doesn't have that field defined as an array, then it simply won't work.  I'd also caution that this might not be the best approach for storing multiple row-related values, though i suppose it could work with some fixes to your existing code (i'd suggest fixing the indentation in your a!forEach loops in your saveInto and consider whether you need to list the "lobkey" property name quite so many times, for one...)

  • When I try to create lobkey as an array, appian is trying to create one more new table.

    Do I need to create another new ruleInput with referring to newly crated table?

  • 0
    Certified Lead Developer
    in reply to Rao2022

    If you need the "lobkey" field to be multiple in the context of any single item with the primary key "alobkey", then to store this in the database you'd need to make a secondary linked table, having a many-to-one relationship with the "attourneylineofbusiness" table.  This is because a SQL table doesn't handle nesting within individual columns of a single table.

    If your need is more low-key, then an alternate way to handle this would be to create a column (let's call it "lobKeyJsonString", TEXT type, and within that, you can store a JSON string which is the result of wrapping your selected "lob key" entries first in a simple array and then converting to a JSON string.  that would look something like this:

    a!multipleDropdownField(
      label: "LOB" & fv!index,
      labelPosition: "ABOVE",
      placeholder: "Select a Line of Business",
      choiceLabels: index(local!lineOfBusiness, "lobname", ""),
      choiceValues: index(local!lineOfBusiness, "lobkey", ""),
      value: a!fromJson(a!defaultValue(fv!item.lobKeyJsonString, "[]")),
      saveInto: {
        a!save(
          fv!item.lobKeyJsonString,
          a!toJson(save!value)
        )
      },
      required: true
    )

Reply
  • 0
    Certified Lead Developer
    in reply to Rao2022

    If you need the "lobkey" field to be multiple in the context of any single item with the primary key "alobkey", then to store this in the database you'd need to make a secondary linked table, having a many-to-one relationship with the "attourneylineofbusiness" table.  This is because a SQL table doesn't handle nesting within individual columns of a single table.

    If your need is more low-key, then an alternate way to handle this would be to create a column (let's call it "lobKeyJsonString", TEXT type, and within that, you can store a JSON string which is the result of wrapping your selected "lob key" entries first in a simple array and then converting to a JSON string.  that would look something like this:

    a!multipleDropdownField(
      label: "LOB" & fv!index,
      labelPosition: "ABOVE",
      placeholder: "Select a Line of Business",
      choiceLabels: index(local!lineOfBusiness, "lobname", ""),
      choiceValues: index(local!lineOfBusiness, "lobkey", ""),
      value: a!fromJson(a!defaultValue(fv!item.lobKeyJsonString, "[]")),
      saveInto: {
        a!save(
          fv!item.lobKeyJsonString,
          a!toJson(save!value)
        )
      },
      required: true
    )

Children
  • Hi,

    Thanks for your advise. To make it simple, I am trying using the below steps.

    Step#1 Created 2 tables ALineOfBusiness & ALineOfBusiness_lobkey (t.txt)

    Step#2 Created a data types for each of the above defined tables.

    Step#3 Created a separate rule inputs for each of those tables.

    I got struck at fitting data into a rule inputs. (sail.txt).

    CREATE TABLE dbo.ALineOfBusiness (ALOBKey INT IDENTITY,RecordID INT,AttorneyKey INT,
    CONSTRAINT PK_ALineOfBusiness PRIMARY KEY (ALOBKey)
    )
    
    CREATE TABLE dbo.ALineOfBusiness_lobkey
    (
    sno int identity(1,1) primary key,
    ALOBKey int ,
    AttorneyKey int,
    lobkey INT,
    )
    
    ALTER TABLE ALineOfBusiness_lobkey
    ADD FOREIGN KEY (ALOBKey) REFERENCES ALineOfBusiness(ALOBKey);

    a!localVariables(
      local!lineOfBusiness: rule!LCM_getLineOfBusinesses(lobkey: null(), lobcode: null()),
      local!attorneys: rule!LCM_getAttorneys(soeid: null(), attorneykey: null()),
      local!selectedAttorney,
      local!selectedAttorneyLOB,
      local!attorneyLOB: {
        a!map(attorneykey: null(), lobkey: null())
      },
      a!formLayout(
        label: "Form",
        contents: {
          a!boxLayout(
            label: "Attorney - Line of Businesses",
            contents: {
              a!gridLayout(
                label: "",
                labelPosition: "ABOVE",
                totalCount: count(local!attorneyLOB),
                headerCells: {
                  a!gridLayoutHeaderCell(label: "Attorney(s)"),
                  a!gridLayoutHeaderCell(label: "Line of Business"),
                  a!gridLayoutHeaderCell(label: "")
                },
                columnConfigs: {
                  a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 1),
                  a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 1),
                  a!gridLayoutColumnConfig(width: "ICON")
                },
                rows: {
                  a!forEach(
                    items: local!attorneyLOB,
                    expression: a!gridRowLayout(
                      contents: {
                        a!dropdownField(
                          label: "Attorney(s)" & fv!index,
                          labelPosition: "ABOVE",
                          helpTooltip: "Attorney(s)",
                          placeholder: "Select a Attorney",
                          choiceLabels: index(local!attorneys, "name", ""),
                          choiceValues: index(local!attorneys, "attorneykey", ""),
                          value: fv!item.attorneykey,
                          saveInto: {
                            fv!item.attorneykey,
                            a!save(
                              target: ri!intakeattorneys,
                              value: a!forEach(
                                items: local!attorneyLOB,
                                expression: { AttorneyKey: fv!item.attorneykey }
                              )
                            )
                          },
                          required: true
                        ),
                        a!multipleDropdownField(
                          label: "LOB" & fv!index,
                          labelPosition: "ABOVE",
                          placeholder: "Select a Line of Business",
                          choiceLabels: index(local!lineOfBusiness, "lobname", ""),
                          choiceValues: index(local!lineOfBusiness, "lobkey", ""),
                          value: fv!item.lobkey,
                          saveInto: {
                            fv!item.lobkey,
                            a!save(
                              ri!attorneyLineOfBusiness,
                              value: a!forEach(
                                items: local!attorneyLOB,
                                expression: { attorneykey: fv!item.attorneykey }
                              )
                            ),
                            a!save(
                              ri!ALineOfBusinesslobkey,
                              value: a!forEach(
                                items: local!attorneyLOB,
                                expression: {
                                  a!forEach(
                                    items: fv!item,
                                    expression: {
                                      attorneykey: fv!item.attorneykey,
                                      lobkey: a!foreach(
                                        items: fv!item,
                                        expression: { lobkey: fv!item.lobkey }
                                      )
                                    }
                                  )
                                }
                              )
                            )
                          },
                          required: true
                        ),
                        a!imageField(
                          label: "delete " & fv!index,
                          images: a!documentImage(
                            document: a!iconIndicator("REMOVE"),
                            altText: "Remove",
                            caption: "Remove ",
                            link: a!dynamicLink(
                              value: fv!index,
                              saveInto: {
                                a!save(
                                  local!attorneyLOB,
                                  remove(local!attorneyLOB, save!value)
                                )
                              },
                              
                            ),
                            showWhen: fv!index > 1
                          ),
                          size: "ICON"
                        )
                      }
                    )
                  )
                },
                selectionSaveInto: {},
                validations: {},
                shadeAlternateRows: true,
                addRowLink: a!dynamicLink(
                  label: "Add",
                  saveInto: {
                    a!save(
                      local!attorneyLOB,
                      append(local!attorneyLOB, save!value)
                    )
                  }
                ),
                rowHeader: 1
              )
            },
            style: "STANDARD",
            marginBelow: "STANDARD"
          )
        },
        buttons: a!buttonLayout(
          primaryButtons: {
            a!buttonWidget(
              label: "Submit",
              submit: true,
              style: "PRIMARY"
            )
          },
          secondaryButtons: {
            a!buttonWidget(
              label: "Cancel",
              value: true,
              saveInto: ri!cancel,
              submit: true,
              style: "NORMAL",
              validate: false
            )
          }
        )
      )
    )

  • 0
    Certified Lead Developer
    in reply to Rao2022

    I think you will need to simplify this somewhat.  At the moment you have a whole 3(!!) levels of nested a!forEach statements, just in the circled portion - you shouldn't need nearly this many, IMHO.

    Also: you might consider making the new "aLineOfBusinessLobKey" CDT a child (nested) CDT of your original one.  I don't do this very often but this is probably a good use case for that - it would simplify the linking/writing of foreign keys to the child table values at write-time, as far as I remember.

  • I have crated appian data type "ALineOfBusiness" with lobkey as an arry, then it created a another table "ALineOfBusiness_lobkey".

    After words, I have created respective rule inputs. But, still I was unable to save multiple lobkeys against each Attorney.

  • 0
    Certified Lead Developer
    in reply to Rao2022

    If the child CDT is nested in the parent CDT, you can save directly into its value(s) in the parent row of the editable grid by saving into "fv!item.childCdtPropertyName".  That would require one and only one a!forEach level in the saveInto of the multiple dropdown field - looping over every value currently in the "save!value" of the dropdown, and initializing a child CDT entry for it.  In this manner you should be able to base the Editable Grid rows directly on the Rule Input CDT and skip the local dictionary stage.

  • 0
    Certified Lead Developer
    in reply to Rao2022

    Here's a 100% generic form relying on a generic, relatively-freshly-created parent/child CDT pair, which handles the "rows of child CDT per parent row based on multi dropdown value" concept.

    a!formLayout(
      label: "Simple Submit form",
      
      contents: {
        a!gridLayout(
          label: "test grid",
          headerCells: {
            a!gridLayoutHeaderCell(label: "label"),
            a!gridLayoutHeaderCell(label: "multiple")
          },
          rows: a!forEach(
            ri!parentCdt,
            a!gridRowLayout(
              contents: {
                a!textField(
                  value: fv!item.parentText1,
                  saveInto: fv!item.parentText1
                ),
                
                a!multipleDropdownField(
                  value: property(fv!item.nestedElement1, "int1", {}),
                  saveInto: {
                    a!save(
                      fv!item.nestedElement1,
                      a!forEach(
                        save!value,
                        {
                          int1: fv!item,
                          text1: "active"
                        }
                      )
                    )
                  },
                  choiceValues: {1, 2, 3},
                  choiceLabels: {1, 2, 3}
                )
              }
            )
          ),
          addRowLink: a!dynamicLink(
            label: "Add",
            saveInto: a!save(
              ri!parentCdt,
              append(
                ri!parentCdt,
                {
                  parentText1: "",
                  nestedElement1: {}
                }
              )
            )
          )
        )
      },
      
      buttons: a!buttonLayout(
        primaryButtons: {
          a!buttonWidget(
            label: "Submit",
            submit: true()
          )
        }
      )
    )

  • Hi,

    Thanks for providing details explanation.

    Is there any way we can get a default row in this editable grid. If we try to use ruleInput "ri!parentCdt" for the gird rows, we are not getting default row until we click "New Field" link.

    Any idea on this.

  • 0
    Certified Lead Developer
    in reply to Rao2022

    You would need to populate it in-process prior to your user input task.  Though I don't think it should really be necessary to have a "default row" - just validate that the users add at least one.

  • Thanks for your reply.

    I don't user input task. I am attaching the SAIL form to the process start node.

    Not sure how I can achieve.

  • +1
    Certified Lead Developer
    in reply to Rao2022

    You can always off-shift your editable grid rows into a local variable instead of directly reading/writing to the Rule Input - in that case you'd declare a "blank" one initially in the local variable definition, then in the "submit" button you'd add an a!save() statemen that mirrors the value of the local variable into the rule input.

  • Thank you so much for all your explanations. I really appreciate.