Editable Grid SAIL

I tried the following SAIL recipe which worked well with Employees CDT as ri! parameter for adding rows. I thought deletion would also be done by the same call using write to datastore smart service in a kind of merging but it did not. I am trying to call another service for deletion with deleted ids stored in another ri! parameter. However I am getting into following two issues.

1) The deleted id is +1 more than rowid

2) When submit button is pressed I am getting error that my deleted ids array is null. 

Could somebody provide me details on what needs to be done?

 

=load(
a!formLayout(
label: "SAIL Example: Add,Update, or Remove Employee Data",
contents: {
a!gridLayout(
totalCount: count(ri!Employees),
headerCells: {
a!gridLayoutHeaderCell(label: "id" ),
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: "" )
},
/* 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:3 ),
a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
a!gridLayoutColumnConfig(width: "ICON")
},
rows: a!forEach(
items: ri!Employees,
expression: a!gridRowLayout(
contents: {
a!integerField(
/* Labels are not visible in grid cells but are necessary to meet accessibility requirements */
label: "first name " & fv!index,
value: fv!item.id,
saveInto: fv!item.id,
required: true
),
/* 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,
placeholderLabel: "-- Select -- ",
choiceLabels: { "Corporate", "Engineering", "Finance", "Human Resources", "Professional Services", "Sales" },
choiceValues: { "Corporate", "Engineering", "Finance", "HR", "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:"123-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 Removal Column*/
a!imageField(
label: "delete " & fv!index,
images: a!documentImage(
document: a!iconIndicator("REMOVE"),
altText: "Remove Employee",
caption: "Remove " & fv!item.firstName & " " & fv!item.lastName,
link: a!dynamicLink(
value: fv!index,
saveInto: {
a!save(ri!Employees, remove(ri!Employees, save!value)),
a!save(ri!DeletedEmployees, append(ri!DeletedEmployees, fv!item.id))  -- ( fv!item.id -1 works logging in correct ids in to array for deletion)
}
)
),
size: "ICON"
)
},
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: 'type!{urn:com:appian:types}Employee'(),
saveInto: {
a!save(ri!Employees, append(ri!Employees,save!value))
}
)
)
},
buttons: a!buttonLayout(
primaryButtons: a!buttonWidgetSubmit(
label: "Submit",
saveInto:{ a!writeToDataStoreEntity(
dataStoreEntity: cons!DS_ENTITY_REF_EMPLOYEE,
valueToStore: ri!Employees
),
a!deleteFromDataStoreEntities(
entity: cons!DS_ENTITY_REF_EMPLOYEE,              -- This failes
identifiers: ri!DeletedEmployees
)
}
)
)
)
)

  Discussion posts and replies are publicly visible

Parents Reply Children
  • Editable grid functionality is to read the data from a CDT and allow adds/deletes inline. So, in may case, my grid shows 20 rows having returned from database. I delete one of it. I can submit the transaction to DB first and then add. But, decided to add a new row before hitting submit. I should end up essentially 20 rows in database, and, I should have a new row added and a old row removed. So, in my example, I deleted rowid 56 and added rowid 144 with new information. Hope that explains.
  • I could make the functionality work well by doing some changes. The following code works very well for inserts/deletes at the same time and also does not depend on the surrogate keys ( entity primary keys ) for being contiguous and match the count of rows.

    =load(
    a!formLayout(
    label: "SAIL Example: Add,Update, or Remove Employee Data",
    contents: {
    a!gridLayout(
    totalCount: count(ri!Employees),
    headerCells: {
    a!gridLayoutHeaderCell(label: "id" ),
    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: "" )
    },
    /* 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:3 ),
    a!gridLayoutColumnConfig(width: "DISTRIBUTE", weight:2 ),
    a!gridLayoutColumnConfig(width: "ICON")
    },
    rows: a!forEach(
    items: ri!Employees,
    expression: a!gridRowLayout(
    contents: {
    a!integerField(
    /* Labels are not visible in grid cells but are necessary to meet accessibility requirements */
    label: "id " & fv!item.id,
    value: fv!item.id,
    saveInto: fv!item.id,
    required: true
    ),
    /* 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!item.id,
    value: fv!item.firstName,
    saveInto: fv!item.firstName,
    required: true
    ),
    /* For the Last Name Column*/
    a!textField(
    label: "last name " & fv!item.id,
    value: fv!item.lastName,
    saveInto: fv!item.lastName,
    required:true
    ),
    /* For the Department Column*/
    a!dropdownField(
    label: "department " & fv!item.id,
    placeholderLabel: "-- Select -- ",
    choiceLabels: { "Corporate", "Engineering", "Finance", "Human Resources", "Professional Services", "Sales" },
    choiceValues: { "Corporate", "Engineering", "Finance", "HR", "Professional Services", "Sales" },
    value: fv!item.department,
    saveInto: fv!item.department,
    required:true
    ),
    /* For the Title Column*/
    a!textField(
    label: "title " & fv!item.id,
    value: fv!item.title,
    saveInto: fv!item.title,
    required:true
    ),
    /* For the Phone Number Column*/
    a!textField(
    label: "phone number " & fv!item.id,
    placeholder:"123-456-7890",
    value: fv!item.phoneNumber,
    saveInto: fv!item.phoneNumber
    ),
    /* For the Start Date Column*/
    a!dateField(
    label: "start date " & fv!item.id,
    value: fv!item.startDate,
    saveInto: fv!item.startDate,
    required:true,
    align: "RIGHT"
    ),
    /* For the Removal Column*/
    a!imageField(
    label: "delete " & fv!item.id,
    images: a!documentImage(
    document: a!iconIndicator("REMOVE"),
    altText: "Remove Employee",
    caption: "Remove " & fv!item.firstName & " " & fv!item.lastName,
    link: a!dynamicLink(
    value: fv!item.id,
    saveInto: {
    a!save(ri!DeletedEmployees, append(ri!DeletedEmployees, fv!item.id)),
    a!save(ri!Employees, remove(ri!Employees, wherecontains(ri!DeletedEmployees, ri!Employees.id))),
    a!deleteFromDataStoreEntities(
    a!entityDataIdentifiers(
    entity: cons!DS_ENTITY_REF_EMPLOYEE,
    identifiers: ri!DeletedEmployees
    )
    )
    }
    )
    ),
    size: "ICON"
    )
    },
    id: fv!item.id
    )
    )
    ,
    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: 'type!{urn:com:appian:types}Employee'(),
    saveInto: {
    a!save(ri!Employees, append(ri!Employees,save!value))
    }
    )
    )
    },
    buttons: a!buttonLayout(
    primaryButtons: a!buttonWidgetSubmit(
    label: "Submit",
    saveInto:{
    a!save(ri!DeletedEmployees, {}),
    a!writeToDataStoreEntity(
    dataStoreEntity: cons!DS_ENTITY_REF_EMPLOYEE,
    valueToStore: ri!Employees
    )
    }
    )
    )
    )
    )