Pagination in Editable Grid

Hi,

1)I want to Implement pagination in Editable Grid please guide me.

2)Add sorting arrows in Editable Grid header columns for sorting purpose.

Appreciate your help!!

Regards

Nishtha Bhatnagar

  Discussion posts and replies are publicly visible

Parents
  • On top of what Danny proposed as a solution, you can create the pagination functionality itself as a common component for use also in other Grids. 

    You only have to create a generic interface with only 3 rule inputs:

    startIndex (int):  pass the pagingInfo.startIndex,

    batchSize (int): pass the pagingInfo.batshSize,

    totalCount (int): pass the local!datasubset.data

    and make a call of this common interface after your grid and you will be fine. 

    a!localVariables(
      a!sideBySideLayout(
        items: {
          a!sideBySideItem(
            item: a!richTextDisplayField(
              align: "RIGHT",
              value: {
                /* Left Angle */
                a!richTextIcon(
                  icon: "angle-double-left",
                  link: a!dynamicLink(
                    saveInto: {
                      a!save(ri!startIndex, 1),                  
                    },
                    showWhen: ri!startIndex <> 1
                  ),
                  linkStyle: "STANDALONE",
                  color: if(
                    ri!startIndex <> 1,
                    "STANDARD",
                    "SECONDARY"
                  )
                ),
                a!richTextIcon(
                  icon: "angle-left",
                  link: a!dynamicLink(
                    showWhen: ri!startIndex <> 1,
                    saveInto: a!save(
                      ri!startIndex,
                      ri!startIndex - ri!batchSize
                    )
                  ),
                  linkStyle: "STANDALONE",
                  color: if(
                    ri!startIndex <> 1,
                    "STANDARD",
                    "SECONDARY"
                  )
                ),
                /* Start Index */
                a!richTextItem(
                  text: {
                    ri!startIndex, 
                    " - ",
                    if(
                      ri!startIndex + ri!batchSize - 1 > ri!totalCount,
                      ri!totalCount,
                      ri!startIndex + ri!batchSize - 1
                    )
                  },
                  style: "STRONG"
                ),
                /* Total Count */
                a!richTextItem(
                  text: {
                    " of ", 
                    ri!totalCount
                  }
                ),
                /* Right Angle */
                a!richTextIcon(
                  icon: "angle-right",
                  link: a!dynamicLink(
                    showWhen: (ri!startIndex + ri!batchSize - 1) < ri!totalCount,
                    label: "",
                    saveInto: a!save(
                      ri!startIndex,
                      ri!startIndex + ri!batchSize
                    )
                  ),
                  linkStyle: "STANDALONE",
                  color: if(                
                    ri!startIndex + ri!batchSize - 1 < ri!totalCount,                
                    "STANDARD",
                    "SECONDARY"
                  )           
                ),
                a!richTextIcon(
                  icon: "angle-double-right",
                  link: a!dynamicLink(
                    saveInto: {
                      a!save(
                        ri!startIndex, 
                        if(
                          mod(ri!totalCount, ri!batchSize) = 0,
                          ri!totalCount - ri!batchSize + 1,
                          ri!totalCount - mod(ri!totalCount, ri!batchSize) + 1
                        )
                      )
                    },
                    showWhen: ri!startIndex + ri!batchSize - 1 < ri!totalCount
                  ),
                  linkStyle: "STANDALONE",
                  color: if(                
                    ri!startIndex + ri!batchSize - 1 < ri!totalCount,                
                    "STANDARD",
                    "SECONDARY"
                  )
                )
              }
            )
          )
        }
      )
    )

Reply
  • On top of what Danny proposed as a solution, you can create the pagination functionality itself as a common component for use also in other Grids. 

    You only have to create a generic interface with only 3 rule inputs:

    startIndex (int):  pass the pagingInfo.startIndex,

    batchSize (int): pass the pagingInfo.batshSize,

    totalCount (int): pass the local!datasubset.data

    and make a call of this common interface after your grid and you will be fine. 

    a!localVariables(
      a!sideBySideLayout(
        items: {
          a!sideBySideItem(
            item: a!richTextDisplayField(
              align: "RIGHT",
              value: {
                /* Left Angle */
                a!richTextIcon(
                  icon: "angle-double-left",
                  link: a!dynamicLink(
                    saveInto: {
                      a!save(ri!startIndex, 1),                  
                    },
                    showWhen: ri!startIndex <> 1
                  ),
                  linkStyle: "STANDALONE",
                  color: if(
                    ri!startIndex <> 1,
                    "STANDARD",
                    "SECONDARY"
                  )
                ),
                a!richTextIcon(
                  icon: "angle-left",
                  link: a!dynamicLink(
                    showWhen: ri!startIndex <> 1,
                    saveInto: a!save(
                      ri!startIndex,
                      ri!startIndex - ri!batchSize
                    )
                  ),
                  linkStyle: "STANDALONE",
                  color: if(
                    ri!startIndex <> 1,
                    "STANDARD",
                    "SECONDARY"
                  )
                ),
                /* Start Index */
                a!richTextItem(
                  text: {
                    ri!startIndex, 
                    " - ",
                    if(
                      ri!startIndex + ri!batchSize - 1 > ri!totalCount,
                      ri!totalCount,
                      ri!startIndex + ri!batchSize - 1
                    )
                  },
                  style: "STRONG"
                ),
                /* Total Count */
                a!richTextItem(
                  text: {
                    " of ", 
                    ri!totalCount
                  }
                ),
                /* Right Angle */
                a!richTextIcon(
                  icon: "angle-right",
                  link: a!dynamicLink(
                    showWhen: (ri!startIndex + ri!batchSize - 1) < ri!totalCount,
                    label: "",
                    saveInto: a!save(
                      ri!startIndex,
                      ri!startIndex + ri!batchSize
                    )
                  ),
                  linkStyle: "STANDALONE",
                  color: if(                
                    ri!startIndex + ri!batchSize - 1 < ri!totalCount,                
                    "STANDARD",
                    "SECONDARY"
                  )           
                ),
                a!richTextIcon(
                  icon: "angle-double-right",
                  link: a!dynamicLink(
                    saveInto: {
                      a!save(
                        ri!startIndex, 
                        if(
                          mod(ri!totalCount, ri!batchSize) = 0,
                          ri!totalCount - ri!batchSize + 1,
                          ri!totalCount - mod(ri!totalCount, ri!batchSize) + 1
                        )
                      )
                    },
                    showWhen: ri!startIndex + ri!batchSize - 1 < ri!totalCount
                  ),
                  linkStyle: "STANDALONE",
                  color: if(                
                    ri!startIndex + ri!batchSize - 1 < ri!totalCount,                
                    "STANDARD",
                    "SECONDARY"
                  )
                )
              }
            )
          )
        }
      )
    )

Children
  • Hi ,

    Thanks for reply .Appreciate if you can show how to use this function  . 

    Regards

    Nishtha

  • Just copy and paste the code in an empty interface and you will find it out

  • Hii Dimitris,

    Here is my code :

    a!localVariables(
    local!SortedEmployeeData:"FirstName",
    local!Employeedata: rule!ED_GetEmployeeData(local!SortedEmployeeData),
    local!deletedEmployeeIds,

    a!formLayout(
    label: "Employee Details: Add, Update or Delete Employee Data",
    contents: {
    a!dropdownField(
    label: "Select a field which you want to sort the columns values",
    labelPosition: "ABOVE",
    placeholder: "--- Select a Field---",
    choiceLabels: {"FirstName", "LastName", "Email", "Address",
    "Department", "Designation", "ContactNumber", "Date Of Joining",
    "Gender"},
    choiceValues: {"FirstName", "LastName", "Email", "Address",
    "Department", "Designation", "ContactNumber", "Date Of Joining",
    "Gender"},
    value:local!SortedEmployeeData,
    saveInto: {value:local!SortedEmployeeData},
    searchDisplay: "AUTO",
    validations: {}
    ),
    a!gridLayout(
    totalCount: count( local!Employeedata),
    /*totalCount: 5,*/
    headerCells: {
    a!gridLayoutHeaderCell(label: "FirstName" ),
    a!gridLayoutHeaderCell(label: "LastName" ),
    a!gridLayoutHeaderCell(label: "Email" ),
    a!gridLayoutHeaderCell(label: "Address" ),
    a!gridLayoutHeaderCell(label: "Department" ),
    a!gridLayoutHeaderCell(label: "Designation" ),
    a!gridLayoutHeaderCell(label: "Contact Number" ),
    a!gridLayoutHeaderCell(label: "Date Of Joining" ),
    a!gridLayoutHeaderCell(label: "Gender" ),

    /*a!gridLayoutHeaderCell(label: "Start Date", align: "RIGHT" ),*/
    /* For the "Remove" column */
    a!gridLayoutHeaderCell(label: "" )
    },
    /* Only needed when some columns need to be narrow */
    columnConfigs: {
    a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
    a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2),
    a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
    a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
    a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
    a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
    a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
    a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
    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!Employeedata,
    expression: a!gridRowLayout(
    id:fv!item,
    /*id: fv!index,*/
    contents: {
    /* For the FirstName Column*/
    a!textField(
    /* Labels are not visible in grid cells but are necessary to meet accessibility requirements */
    label: "FirstName " & fv!index,
    value: fv!item.FirstName,
    saveInto: fv!item.FirstName,
    required: true
    ),
    /* For the lastName Column*/
    a!textField(
    label: "LastName " & fv!index,
    value: fv!item.LastName,
    saveInto: fv!item.LastName,
    required:true
    ),
    /* For the Email Address Column*/

    a!textField(
    label: "Email" & fv!index,
    value: fv!item.Email,
    saveInto: fv!item.Email,
    required:true,
    validations: {if(regexmatch("^[A-Z0-9\'\+\&\%_-]+(\.{0,1}[A-Z0-9\'\+\&\%_-]+)*[@]{1}[A-Z0-9.-]*[A-Z0-9-]+[.]{1}[A-Z]{2,6}$",
    fv!item.Email),"","provide valid email address"

    )}
    ),
    /* For the Address Column*/
    a!textField(
    label: " Address" & fv!index,
    value: fv!item.Address,
    saveInto: fv!item.Address,
    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 Designation Column*/
    a!dropdownField(
    label: "Designation " & fv!index,
    placeholder: "-- Select -- ",
    choiceLabels:{"Software Engineer","Support Engineer","Tester","Marking Specialist","Web Developer",".Net Developer","Graphic Designer","Application Developer"},
    choiceValues:{"Software Engineer","Support Engineer","Tester","Marking Specialist","Web Developer",".Net Developer","Graphic Designer","Application Developer"} ,
    value: fv!item.Designation,
    saveInto: fv!item.Designation,
    required:true
    ),

    /* For the ContactNumber Column*/
    a!textField(
    label: "ContactNumber" & fv!index,
    /*placeholder:"555-456-7890",*/
    value: fv!item.ContactNumber,
    saveInto: fv!item.ContactNumber,
    validations: {if(regexmatch(
    "^(\+\d{1,3}[- ]?)?\d{10}$",
    fv!item.ContactNumber),"","provide valid contact number")}

    /*validations:if(len(fv!item.ContactNumber)=10,"","please enter valid Number")*/


    ),


    a!dateField(
    label: "Date Of Joining " & fv!index,
    value: fv!item.HireDate,
    saveInto: fv!item.HireDate,
    required:true,
    align: "RIGHT"
    ),
    /* For the Gender Column*/
    a!dropdownField(
    label: "Gender " & fv!index,
    placeholder: "-- Select -- ",
    choiceLabels: {"Male","Female"},
    choiceValues: {"Male","Female"},

    value: fv!item.Gender,
    saveInto: fv!item.Gender,
    required:true
    ),

    /* For the Removal Column*/
    a!richTextDisplayField(
    value: a!richTextIcon(
    icon: "trash-o",
    altText: "delete " & fv!index,
    caption: "Remove " & fv!item.FirstName & " " & fv!item.LastName,
    link: a!dynamicLink(
    value: fv!index,
    saveInto: {

    if(
    isnull(fv!item.Id),
    {},
    a!save(local!deletedEmployeeIds,append(local!deletedEmployeeIds,fv!item.Id))

    ),
    a!save(ri!Del,true),
    a!save(ri!Del_Id,local!deletedEmployeeIds),
    a!save(local!Employeedata, remove(local!Employeedata, save!value))



    }
    ),
    linkStyle: "STANDALONE",
    color: "NEGATIVE"
    )
    )
    }
    )
    ),
    selectionStyle: "ROW_HIGHLIGHT",
    selectionRequired: false,
    addRowlink: a!dynamicLink(
    label: "Add Employee",

    value: {
    'type!{urn:com:appian:types:ED}ED_Employee_Details_dt'()
    },
    saveInto: {
    a!save(local!Employeedata, append(local!Employeedata, save!value))
    }
    ),

    shadeAlternateRows: true,
    spacing: "STANDARD",
    rowHeader: 1
    )

    },
    buttons: a!buttonLayout(
    primaryButtons: a!buttonWidget(
    label: "Submit",
    saveInto: {a!save(ri!item,local!Employeedata)},
    submit: true,
    style: "PRIMARY"
    ),
    secondaryButtons: {
    a!buttonWidget(
    label: "Cancel",
    value: true,
    saveInto: {ri!Cancel},
    submit: true,
    style: "NORMAL",
    validate: false
    )
    }
    )
    )
    )

    can you help me how to implement  your code in my code ?

  • 0
    Certified Senior Developer
    in reply to jojog0002

    Hello jojog,
    please use the following for inserting code. I makes it way easier to read. :) 

  • a!localVariables(
      local!SortedEmployeeData:"FirstName",
      local!Employeedata: rule!ED_GetEmployeeData(local!SortedEmployeeData),
      local!deletedEmployeeIds,
    
      a!formLayout(
        label: "Employee Details: Add, Update or Delete Employee Data",
        contents: {
          a!dropdownField(
            label: "Select a field which you want to sort the columns values",
            labelPosition: "ABOVE",
            placeholder: "--- Select a Field---",
            choiceLabels: {"FirstName", "LastName", "Email", "Address",
                            "Department", "Designation", "ContactNumber", "Date Of Joining",
                            "Gender"},
            choiceValues: {"FirstName", "LastName", "Email", "Address",
                            "Department", "Designation", "ContactNumber", "Date Of Joining",
                            "Gender"},
            value:local!SortedEmployeeData,
            saveInto: {value:local!SortedEmployeeData},
            searchDisplay: "AUTO",
            validations: {}
          ),
          a!gridLayout(
            totalCount: count( local!Employeedata),
            /*totalCount: 5,*/
            headerCells: {
              a!gridLayoutHeaderCell(label: "FirstName" ),
              a!gridLayoutHeaderCell(label: "LastName" ),
              a!gridLayoutHeaderCell(label: "Email" ),
              a!gridLayoutHeaderCell(label: "Address" ),
              a!gridLayoutHeaderCell(label: "Department" ),
              a!gridLayoutHeaderCell(label: "Designation" ),
              a!gridLayoutHeaderCell(label: "Contact Number" ),
              a!gridLayoutHeaderCell(label: "Date Of Joining" ),
              a!gridLayoutHeaderCell(label: "Gender" ),
            
              /*a!gridLayoutHeaderCell(label: "Start Date", align: "RIGHT" ),*/
              /* For the "Remove" column */
              a!gridLayoutHeaderCell(label: "" )
            },
            /* Only needed when some columns need to be narrow */
            columnConfigs: {
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
              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!Employeedata,
              expression: a!gridRowLayout(
                id:fv!item,
                /*id: fv!index,*/
                contents: {
                  /* For the FirstName Column*/
                  a!textField(
                    /* Labels are not visible in grid cells but are necessary to meet accessibility requirements */
                    label: "FirstName " & fv!index,
                    value: fv!item.FirstName,
                    saveInto: fv!item.FirstName,
                    required: true
                  ),
                  /* For the lastName Column*/
                  a!textField(
                    label: "LastName " & fv!index,
                    value: fv!item.LastName,
                    saveInto: fv!item.LastName,
                    required:true
                  ),
                  /* For the Email Address Column*/
    
                  a!textField(
                    label: "Email" & fv!index,
                    value: fv!item.Email,
                    saveInto: fv!item.Email,
                    required:true,
                    validations: {if(regexmatch("^[A-Z0-9\'\+\&\%_-]+(\.{0,1}[A-Z0-9\'\+\&\%_-]+)*[@]{1}[A-Z0-9.-]*[A-Z0-9-]+[.]{1}[A-Z]{2,6}$",
                    fv!item.Email),"","provide valid email address"
    
                    )}
                  ),
                  /* For the Address Column*/
                  a!textField(
                    label: " Address" & fv!index,
                    value: fv!item.Address,
                    saveInto: fv!item.Address,
                    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 Designation Column*/
                  a!dropdownField(
                    label: "Designation " & fv!index,
                    placeholder: "-- Select -- ",
                    choiceLabels:{"Software Engineer","Support Engineer","Tester","Marking Specialist","Web Developer",".Net Developer","Graphic Designer","Application Developer"},
                    choiceValues:{"Software Engineer","Support Engineer","Tester","Marking Specialist","Web Developer",".Net Developer","Graphic Designer","Application Developer"} ,
                    value: fv!item.Designation,
                    saveInto: fv!item.Designation,
                    required:true
                  ),
    
                  /* For the ContactNumber Column*/
                  a!textField(
                    label: "ContactNumber" & fv!index,
                    /*placeholder:"555-456-7890",*/
                    value: fv!item.ContactNumber,
                    saveInto: fv!item.ContactNumber,
                    validations: {if(regexmatch(
                      "^(\+\d{1,3}[- ]?)?\d{10}$",
                      fv!item.ContactNumber),"","provide valid contact number")}
                  
                    /*validations:if(len(fv!item.ContactNumber)=10,"","please enter valid Number")*/
                  
                
                  ),
    
    
                  a!dateField(
                    label: "Date Of Joining " & fv!index,
                    value: fv!item.HireDate,
                    saveInto: fv!item.HireDate,
                    required:true,
                    align: "RIGHT"
                  ),
                  /* For the Gender Column*/
                  a!dropdownField(
                    label: "Gender " & fv!index,
                    placeholder: "-- Select -- ",
                    choiceLabels: {"Male","Female"},
                    choiceValues: {"Male","Female"},
    
                    value: fv!item.Gender,
                    saveInto: fv!item.Gender,
                    required:true
                  ),
                
                  /* For the Removal Column*/
                  a!richTextDisplayField(
                    value: a!richTextIcon(
                      icon: "trash-o",
                      altText: "delete " & fv!index,
                      caption: "Remove " & fv!item.FirstName & " " & fv!item.LastName,
                      link: a!dynamicLink(
                        value: fv!index,
                        saveInto: {
                          
                          if(
                            isnull(fv!item.Id),
                            {},
                            a!save(local!deletedEmployeeIds,append(local!deletedEmployeeIds,fv!item.Id))
                            
                          ),
                          a!save(ri!Del,true),
                          a!save(ri!Del_Id,local!deletedEmployeeIds),
                          a!save(local!Employeedata, remove(local!Employeedata, save!value))
                          
                          
                          
                        }
                      ),
                      linkStyle: "STANDALONE",
                      color: "NEGATIVE"
                    )
                  )
                }
              )
            ),
            selectionStyle: "ROW_HIGHLIGHT",
            selectionRequired: false,
            addRowlink: a!dynamicLink(
              label: "Add Employee",
    
              value: {
                'type!{urn:com:appian:types:ED}ED_Employee_Details_dt'()
              },
              saveInto: {
                a!save(local!Employeedata, append(local!Employeedata, save!value))
              }
            ),
           
            shadeAlternateRows: true,
            spacing: "STANDARD",
            rowHeader: 1
          )
         
        },
        buttons: a!buttonLayout(
          primaryButtons: a!buttonWidget(
            label: "Submit",
            saveInto: {a!save(ri!item,local!Employeedata)},
            submit: true,
            style: "PRIMARY"
          ),
          secondaryButtons: {
            a!buttonWidget(
              label: "Cancel",
              value: true,
              saveInto: {ri!Cancel},
              submit: true,
              style: "NORMAL",
              validate: false
            )
          }
        )
      )
    )

  • Hi jojog,

    I have made some changes in your code that are needed for creating the pagination functionality.

    You have to create some local variables first in your code for setting the pagination and create a datasubset of your Employee list.

    Instead of rule!DS_customPaginationForGrids() put the rule name of your expression rule you created with the pagination functionality.

    Let me know the outcome after you test it. 

    a!localVariables(
      local!SortedEmployeeData: "FirstName",
      local!Employeedata: rule!ED_GetEmployeeData(local!SortedEmployeeData),
      local!deletedEmployeeIds,
      /* Create Pagination */
      local!startIndex: 1,
      local!batchSize: 4,
      local!pagingInfo: a!pagingInfo(
        startIndex: local!startIndex,
        batchSize: local!batchSize
      ),
      local!datasubset: todatasubset(
        arrayToPage: local!Employeedata,
        pagingConfiguration: local!pagingInfo
      ),
      a!formLayout(
        label: "Employee Details: Add, Update or Delete Employee Data",
        contents: {
          a!dropdownField(
            label: "Select a field which you want to sort the columns values",
            labelPosition: "ABOVE",
            placeholder: "--- Select a Field---",
            choiceLabels: {
              "FirstName",
              "LastName",
              "Email",
              "Address",
              "Department",
              "Designation",
              "ContactNumber",
              "Date Of Joining",
              "Gender"
            },
            choiceValues: {
              "FirstName",
              "LastName",
              "Email",
              "Address",
              "Department",
              "Designation",
              "ContactNumber",
              "Date Of Joining",
              "Gender"
            },
            value: local!SortedEmployeeData,
            saveInto: { value: local!SortedEmployeeData },
            searchDisplay: "AUTO",
            validations: {}
          ),
          a!gridLayout(
            totalCount: local!datasubset.totalCount,
            /*totalCount: 5,*/
            headerCells: {
              a!gridLayoutHeaderCell(label: "FirstName"),
              a!gridLayoutHeaderCell(label: "LastName"),
              a!gridLayoutHeaderCell(label: "Email"),
              a!gridLayoutHeaderCell(label: "Address"),
              a!gridLayoutHeaderCell(label: "Department"),
              a!gridLayoutHeaderCell(label: "Designation"),
              a!gridLayoutHeaderCell(label: "Contact Number"),
              a!gridLayoutHeaderCell(label: "Date Of Joining"),
              a!gridLayoutHeaderCell(label: "Gender"),
              /*a!gridLayoutHeaderCell(label: "Start Date", align: "RIGHT" ),*/
              /* For the "Remove" column */
              a!gridLayoutHeaderCell(label: "")
            },
            /* Only needed when some columns need to be narrow */
            columnConfigs: {
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
              a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight: 2),
              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!datasubset,
              expression: a!gridRowLayout(
                id: fv!item,
                /*id: fv!index,*/
                contents: {
                  /* For the FirstName Column*/
                  a!textField(
                    /* Labels are not visible in grid cells but are necessary to meet accessibility requirements */
                    label: "FirstName " & fv!index,
                    value: fv!item.FirstName,
                    saveInto: fv!item.FirstName,
                    required: true
                  ),
                  /* For the lastName Column*/
                  a!textField(
                    label: "LastName " & fv!index,
                    value: fv!item.LastName,
                    saveInto: fv!item.LastName,
                    required: true
                  ),
                  /* For the Email Address Column*/
                  a!textField(
                    label: "Email" & fv!index,
                    value: fv!item.Email,
                    saveInto: fv!item.Email,
                    required: true,
                    validations: {
                      if(
                        regexmatch(
                          "^[A-Z0-9\'\+\&\%_-]+(\.{0,1}[A-Z0-9\'\+\&\%_-]+)*[@]{1}[A-Z0-9.-]*[A-Z0-9-]+[.]{1}[A-Z]{2,6}$",
                          fv!item.Email
                        ),
                        "",
                        "provide valid email address"
                      )
                    }
                  ),
                  /* For the Address Column*/
                  a!textField(
                    label: " Address" & fv!index,
                    value: fv!item.Address,
                    saveInto: fv!item.Address,
                    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 Designation Column*/
                  a!dropdownField(
                    label: "Designation " & fv!index,
                    placeholder: "-- Select -- ",
                    choiceLabels: {
                      "Software Engineer",
                      "Support Engineer",
                      "Tester",
                      "Marking Specialist",
                      "Web Developer",
                      ".Net Developer",
                      "Graphic Designer",
                      "Application Developer"
                    },
                    choiceValues: {
                      "Software Engineer",
                      "Support Engineer",
                      "Tester",
                      "Marking Specialist",
                      "Web Developer",
                      ".Net Developer",
                      "Graphic Designer",
                      "Application Developer"
                    },
                    value: fv!item.Designation,
                    saveInto: fv!item.Designation,
                    required: true
                  ),
                  /* For the ContactNumber Column*/
                  a!textField(
                    label: "ContactNumber" & fv!index,
                    /*placeholder:"555-456-7890",*/
                    value: fv!item.ContactNumber,
                    saveInto: fv!item.ContactNumber,
                    validations: {
                      if(
                        regexmatch(
                          "^(\+\d{1,3}[- ]?)?\d{10}$",
                          fv!item.ContactNumber
                        ),
                        "",
                        "provide valid contact number"
                      )
                    }/*validations:if(len(fv!item.ContactNumber)=10,"","please enter valid Number")*/
                    
                  ),
                  a!dateField(
                    label: "Date Of Joining " & fv!index,
                    value: fv!item.HireDate,
                    saveInto: fv!item.HireDate,
                    required: true,
                    align: "RIGHT"
                  ),
                  /* For the Gender Column*/
                  a!dropdownField(
                    label: "Gender " & fv!index,
                    placeholder: "-- Select -- ",
                    choiceLabels: { "Male", "Female" },
                    choiceValues: { "Male", "Female" },
                    value: fv!item.Gender,
                    saveInto: fv!item.Gender,
                    required: true
                  ),
                  /* For the Removal Column*/
                  a!richTextDisplayField(
                    value: a!richTextIcon(
                      icon: "trash-o",
                      altText: "delete " & fv!index,
                      caption: "Remove " & fv!item.FirstName & " " & fv!item.LastName,
                      link: a!dynamicLink(
                        value: fv!index,
                        saveInto: {
                          if(
                            isnull(fv!item.Id),
                            {},
                            a!save(
                              local!deletedEmployeeIds,
                              append(local!deletedEmployeeIds, fv!item.Id)
                            )
                          ),
                          a!save(ri!Del, true),
                          a!save(ri!Del_Id, local!deletedEmployeeIds),
                          a!save(
                            local!Employeedata,
                            remove(local!Employeedata, save!value)
                          )
                        }
                      ),
                      linkStyle: "STANDALONE",
                      color: "NEGATIVE"
                    )
                  )
                }
              )
            ),
            selectionStyle: "ROW_HIGHLIGHT",
            selectionRequired: false,
            addRowlink: a!dynamicLink(
              label: "Add Employee",
              value: { 'type!{urn:com:appian:types:ED}ED_Employee_Details_dt'() },
              saveInto: {
                a!save(
                  local!Employeedata,
                  append(local!Employeedata, save!value)
                )
              }
            ),
            shadeAlternateRows: true,
            spacing: "STANDARD",
            rowHeader: 1
          ),
          
          /* Pagination Functionality */
          rule!DS_customPaginationForGrids(
            startIndex: local!startIndex,
            batchSize: local!batchSize,
            totalCount: local!datasubset.totalCount
          ),
          
        },
        buttons: a!buttonLayout(
          primaryButtons: a!buttonWidget(
            label: "Submit",
            saveInto: { a!save(ri!item, local!Employeedata) },
            submit: true,
            style: "PRIMARY"
          ),
          secondaryButtons: {
            a!buttonWidget(
              label: "Cancel",
              value: true,
              saveInto: { ri!Cancel },
              submit: true,
              style: "NORMAL",
              validate: false
            )
          }
        )
      )
    )

  • Hi Dimitris,

    please also help me for creation a  expression rule for the pagination functionality. 

  • You have everything you need written above on my previous comment. The code for the pagination functionality and how to setup the rule.. Just copy and paste it. That's all.

  • 0
    Certified Senior Developer
    in reply to jojog0002

    Dimitris explained it pretty well.
    Its one way to solve it, but a pretty valid one.
    -> jojog, what are you missing exactly?

  • 0
    Certified Lead Developer
    in reply to Dimitris Soulovaris

    As I noted in the other thread... as far as I can tell from this code, the row-level user changes are only saved up as far as the dataSubset (and i don't see any code that propagates such changes any further than that), but of course that's all overwritten the second the user changes pages. 

    Some additional SaveInto bending-over-backwards would need to be added to promote any user changes back to the source data, but of course at that point, we're talking about such complicated code that most devs would have saved days of heartache and headache by just implementing a paging grid with a row-level "edit" button.