How to save a row order in grid

Hi All,

I'm a beginner of Appian, and I would like to know how to save a row order in a grid.

In a grid in an interface, I put a arrow for up and down to move rows.

I need to save the order, so the changed order should be saved and updated to DB.

I should create a column in DB to save a row order, but it does not work.

What I want to do is ... when I change the row order by clicking arrow icon and the order is changed, I would like to save the ordering information for next time. When a user open the window next time, a user requires to see the row which was changed by user clicking an arrow.

I need your help.....

Best regards,

  Discussion posts and replies are publicly visible

  • a!localVariables(
      /*  
      * local!employess is provided in this recipe as a way to start with hard-coded
      * data. However, this data is identical to the data created from the entity-backed
      * tutorial. Replace the hard-coded data with a query to the employee data store
      * entity and all of the employee records from the tutorial will appear.
      *
      * To replace this data with your own, replace (ctrl+H or cmd+H) all references to
      * local!employees with your data source, either via rule input or local variable.
      */
      local!tempEmployHolder,
      local!employees: {
        a!map(
          id: 1,
          firstName: "John",
          lastName: "Smith",
          department: "Engineering",
          title: "Director",
          phoneNumber: "555-123-4567",
          startDate: today() - 360,
          sequence: 1
        ),
        a!map(
          id: 2,
          firstName: "Michael",
          lastName: "Johnson",
          department: "Finance",
          title: "Analyst",
          phoneNumber: "555-987-6543",
          startDate: today() - 360,
          sequence: 2
        ),
        a!map(
          id: 3,
          firstName: "Mary",
          lastName: "Reed",
          department: "Engineering",
          title: "Software Engineer",
          phoneNumber: "555-456-0123",
          startDate: today() - 240,
          sequence: 3
        ),
    
      },
      a!formLayout(
        label: "Example: Add,Update, or Remove Employee Data",
        contents: {
          a!gridLayout(
            totalCount: count(local!employees),
            headerCells: {
              a!gridLayoutHeaderCell(label: "First Name"),
              a!gridLayoutHeaderCell(label: "Last Name"),
              a!gridLayoutHeaderCell(label: "Department"),
              a!gridLayoutHeaderCell(label: "Title"),
              a!gridLayoutHeaderCell(label: "Phone Number"),
              a!gridLayoutHeaderCell(label: "Start Date", align: "RIGHT"),
              /* For the "Remove" column */
              a!gridLayoutHeaderCell(label: ""),
              a!gridLayoutHeaderCell(label: "")
            },
            /* Only needed when some columns need to be narrow */
            columnConfigs: {
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 3),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 3),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 3),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 3),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 3),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
              a!gridLayoutColumnConfig(width: "ICON"),
              a!gridLayoutColumnConfig(width: "ICON")
            },
            /*
            * a!forEach() will take local!employee data and used that data to loop through an
            * expression that creates each row.
            *
            * When modifying the recipe to work with your data, you only need to change:
            * 1.) the number of fields in each row
            * 2.) the types of fields for each column (i.e. a!textField() for text data elements)
            * 3.) the fv!item elements. For example fv!item.firstName would change to fv!item.yourdata
            */
            rows: a!forEach(
              items: local!employees,
              expression: a!gridRowLayout(
                contents: {
                  /* For the First Name Column*/
                  a!textField(
                    /* Labels are not visible in grid cells but are necessary to meet accessibility requirements */
                    label: "first name " & fv!index,
                    value: fv!item.firstName,
                    saveInto: fv!item.firstName,
                    required: true
                  ),
                  /* For the Last Name Column*/
                  a!textField(
                    label: "last name " & fv!index,
                    value: fv!item.lastName,
                    saveInto: fv!item.lastName,
                    required: true
                  ),
                  /* For the Department Column*/
                  a!dropdownField(
                    label: "department " & fv!index,
                    placeholder: "-- Select -- ",
                    choiceLabels: {
                      "Corporate",
                      "Engineering",
                      "Finance",
                      "Human Resources",
                      "Professional Services",
                      "Sales"
                    },
                    choiceValues: {
                      "Corporate",
                      "Engineering",
                      "Finance",
                      "Human Resources",
                      "Professional Services",
                      "Sales"
                    },
                    value: fv!item.department,
                    saveInto: fv!item.department,
                    required: true
                  ),
                  /* For the Title Column*/
                  a!textField(
                    label: "title " & fv!index,
                    value: fv!item.title,
                    saveInto: fv!item.title,
                    required: true
                  ),
                  /* For the Phone Number Column*/
                  a!textField(
                    label: "phone number " & fv!index,
                    placeholder: "555-456-7890",
                    value: fv!item.phoneNumber,
                    saveInto: fv!item.phoneNumber
                  ),
                  /* For the Start Date Column*/
                  a!dateField(
                    label: "start date " & fv!index,
                    value: fv!item.startDate,
                    saveInto: fv!item.startDate,
                    required: true,
                    align: "RIGHT"
                  ),
                  /* For the Moving Column Up*/
                  a!richTextDisplayField(
                    value: a!richTextIcon(
                      icon: "arrow-circle-o-up",
                      altText: "Move " & fv!index,
                      caption: "Move " & fv!item.firstName & " " & fv!item.lastName,
                      link: a!dynamicLink(
                        value: fv!index,
                        saveInto: {
                          local!employees[fv!index - 1].sequence,
                          a!save(
                            local!employees[fv!index].sequence,
                            fv!index - 1
                          ),
                          a!save(
                            local!tempEmployHolder,
                            index(local!employees, fv!index - 1, null())
                          ),
                          a!save(
                            local!employees,
                            a!update(
                              local!employees,
                              fv!index - 1,
                              index(local!employees, fv!index, null())
                            )
                          ),
                          a!save(
                            local!employees,
                            a!update(
                              local!employees,
                              fv!index,
                              local!tempEmployHolder
                            )
                          ),
                          a!save(local!tempEmployHolder, null())
                        }
                      ),
                      linkStyle: "STANDALONE",
                      color: "NEGATIVE",
                      showWhen: not(fv!isFirst)
                    )
                  ),
                  a!richTextDisplayField(
                    value: a!richTextIcon(
                      icon: "arrow-circle-down",
                      altText: "Move " & fv!index,
                      caption: "Move " & fv!item.firstName & " " & fv!item.lastName,
                      link: a!dynamicLink(
                        value: fv!index,
                        saveInto: {
                          local!employees[fv!index + 1].sequence,
                          a!save(
                            local!employees[fv!index].sequence,
                            fv!index + 1
                          ),
                          a!save(
                            local!tempEmployHolder,
                            index(local!employees, fv!index + 1, null())
                          ),
                          a!save(
                            local!employees,
                            a!update(
                              local!employees,
                              fv!index + 1,
                              index(local!employees, fv!index, null())
                            )
                          ),
                          a!save(
                            local!employees,
                            a!update(
                              local!employees,
                              fv!index,
                              local!tempEmployHolder
                            )
                          ),
                          a!save(local!tempEmployHolder, null())
                        }
                      ),
                      linkStyle: "STANDALONE",
                      color: "NEGATIVE",
                      showWhen: not(fv!isLast)
                    )
                  )
                },
                id: fv!index
              )
            ),
            addRowlink: a!dynamicLink(
              label: "Add Employee",
              /*
               * For your use case, set the value to a blank instance of your CDT using
               * the type constructor, e.g. type!Employee(). Only specify the field
               * if you want to give it a default value e.g. startDate: today()+1.
               */
              value: { startDate: today() + 1 },
              saveInto: {
                a!save(
                  local!employees,
                  append(local!employees, save!value)
                )
              }
            ),
            rowHeader: 1
          )
        },
        buttons: a!buttonLayout(
          primaryButtons: a!buttonWidget(label: "Submit", submit: true)
        )
      )
    )

  • 0
    Certified Lead Developer
    I should create a column in DB to save a row order, but it does not work.

    What exactly "does not work"?

    In short my typical design is like this:

    - "sort" field in DB

    - up/down swaps the items in the underlying data

      - then iterates on the list to renumber the sort value all items

      - then write the data back to the DB

    To get started, a good standalone example is this: https://docs.appian.com/suite/help/24.3/recipe-add-edit-and-remove-data-in-an-inline-editable-grid.html

  • 0
    Certified Senior Developer

      You can use a Id with the above map data . Id will uniquely identify each record same as like Db primary key . You can use below code i just tried for down functionality you can use same for Up as well .

    a!localVariables(
    local!items: {
    { id: 1, item: "Item 1", qty: 1, unitPrice: 10 },
    { id: 2, item: "Item 2", qty: 2, unitPrice: 20 }
    },
    a!gridLayout(
    label: "Products",
    instructions: "Update the item name, quantity, or unit price.",
    headerCells: {
    a!gridLayoutHeaderCell(label: "Item"),
    a!gridLayoutHeaderCell(label: "Qty"),
    a!gridLayoutHeaderCell(label: "Unit Price"),
    a!gridLayoutHeaderCell(label: "Total", align: "RIGHT"),
    a!gridLayoutHeaderCell(label: " "),
    
    },
    rows: a!forEach(
    items: local!items,
    expression: a!gridRowLayout(
    contents: {
    a!textField(
    value: fv!item.item,
    saveInto: fv!item.item
    ),
    a!integerField(value: fv!item.qty, saveInto: fv!item.qty),
    a!floatingPointField(
    value: fv!item.unitPrice,
    saveInto: fv!item.unitPrice
    ),
    a!textField(
    value: a!currency(
    isoCode: "USD",
    value: tointeger(fv!item.qty) * todecimal(fv!item.unitPrice)
    ),
    readOnly: true,
    align: "RIGHT"
    ),
    a!richTextDisplayField(
    value: {
    a!richTextIcon(
    icon: "arrow-circle-down",
    showWhen: not(fv!isLast),
    link: a!dynamicLink(
    saveInto: {
    a!save(
    local!items,
    a!update(
    local!items,
    {fv!index,fv!index+1},
    {index(local!items,(fv!index+1),null()),fv!item}
    )
    )
    }
    )
    ),
    a!richTextIcon(icon: "arrow-circle-up")
    }
    )
    }
    )
    ),
    rowHeader: 1
    )
    )

  • 0
    Certified Lead Developer
    in reply to PavanSrihari

    Makes code more readable.

  • 0
    Certified Lead Developer
    in reply to Kumar Agniwesh

    A simple approach to swap items in a list is this:

    a!update(
      ri!list,
      {ri!index1, ri!index2},
      {ri!list[ri!index2], ri!list[ri!index1]}
    )

    I created a utility expression that includes some range and null checks.

  • Thanks  ,

    will change the code and would also add some comments as well

  • is it possible to break page for the grid? gridField seems to have a "break page " as "page size", but editable grid "gridlayout" does not seem to have the "break page".