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
  • Can you please try replacing your code with this piece of code :

     

    a!deleteFromDataStoreEntities(
    dataToDelete: {
    entity: cons!DS_ENTITY_REF_EMPLOYEE,
    identifiers: ri!DeletedEmployees
    },
    onSuccess: "",
    onError: ""
    )

     

    Also verify your DeletedEmployees variable type and do check whether it is storing correct value.

  • I could make this work with the following code. I had to replace fv!index with fv!item and remove deleted ids from employees at submit time. I am working with a table where the surrogate keys are arbitrary and count does not match with next id. There seems to be a validation in REMOVE wherein it does not allow me to delete a row whose id does not math with the count of items in the grid. Only draw back is that user would not see the deleted row going out of screen till the period of pressing SUBMIT button. Is there any refresh function which could be called to update the grid?

    =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!deleteFromDataStoreEntities(
    a!entityDataIdentifiers(
    entity: cons!DS_ENTITY_REF_EMPLOYEE,
    identifiers: ri!DeletedEmployees
    )
    )
    }
    )
    ),
    size: "ICON"
    )
    },
    id: fv!item.id
    )
    )
    ,
    addRowlink: a!dynamicLink(
    label: "Add Employee",
    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!Employees, remove(ri!Employees, wherecontains(ri!DeletedEmployees, ri!Employees.id))),
    a!save(ri!DeletedEmployees, {}),
    a!writeToDataStoreEntity(
    dataStoreEntity: cons!DS_ENTITY_REF_EMPLOYEE,
    valueToStore: ri!Employees
    )
    }
    )
    )
    )
    )
Reply
  • I could make this work with the following code. I had to replace fv!index with fv!item and remove deleted ids from employees at submit time. I am working with a table where the surrogate keys are arbitrary and count does not match with next id. There seems to be a validation in REMOVE wherein it does not allow me to delete a row whose id does not math with the count of items in the grid. Only draw back is that user would not see the deleted row going out of screen till the period of pressing SUBMIT button. Is there any refresh function which could be called to update the grid?

    =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!deleteFromDataStoreEntities(
    a!entityDataIdentifiers(
    entity: cons!DS_ENTITY_REF_EMPLOYEE,
    identifiers: ri!DeletedEmployees
    )
    )
    }
    )
    ),
    size: "ICON"
    )
    },
    id: fv!item.id
    )
    )
    ,
    addRowlink: a!dynamicLink(
    label: "Add Employee",
    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!Employees, remove(ri!Employees, wherecontains(ri!DeletedEmployees, ri!Employees.id))),
    a!save(ri!DeletedEmployees, {}),
    a!writeToDataStoreEntity(
    dataStoreEntity: cons!DS_ENTITY_REF_EMPLOYEE,
    valueToStore: ri!Employees
    )
    }
    )
    )
    )
    )
Children
No Data