Issues with row selection in a grid

Hi All,

I'm facing some issues with the grid selection in a grid. I'm not sure if it is a bug. I tried using the design pattern 'Master details' https://docs.appian.com/suite/help/20.1/master-detail-pattern.html . But I noticed, the selected row is getting deselected immediately. I'm still trying to understand how the row is getting highlighed in the design pattern even though its value is not saved into 'SelectionSaveInto' parameter. Below is my code which is similar to design pattern. I initially tried with a query rule for the data, but facing the same issue even while providing raw data. My current env is 20.1

{
a!localVariables(

local!employees: {

{comments: "Consideration should be given to annual re-inspection and removal during future refurbishment works.", dateRemoved: "", controlMeasure: "", riskRating: "P4", condition: "S", photoNo: "1,2", sampleNo: "Previously Identified", matrix: "B", type: "CH,AM", location: "Underside of the awning between the Transmitter Building (Equipment Building) and EPP Building", descriptionMaterial: "Fibre cement sheeting", dateIdentified: "13/04/2015", siteName: "Mt Lofty", siteNo: 5018, id: 6}, 
{comments: "Remove as soon as practicable. All ground maintenance works within the vicinity of the cable pit should be suspended immediately until removal works have been completed. If material is removed by a licenced asbestos removal contractor, a clearance inspection and subsequent clearance certificate may be required", dateRemoved: "", controlMeasure: "", riskRating: "P2", condition: "P", photoNo: "3,4", sampleNo: "GB05", matrix: "B", type: "CH,AM", location: "Cable pit surround to the north of the Transmitter Building (Equipment Building) and south of the satellite dishes", descriptionMaterial: "Fibre cement", dateIdentified: "13/04/2015", siteName: "Mt Lofty", siteNo: 5018, id: 7}, 
{comments: "Remove as soon as practicable. All ground maintenance works should ve suspended immediately until removal works have been completed. If material is removed by a licenced asbestos contractor, a clearance inspection and subsequent clearance certificate may be required", dateRemoved: "", controlMeasure: "", riskRating: "P3", condition: "F", photoNo: "7,8", sampleNo: "Similar material as GB06", matrix: "B", type: "NT(CH,AM,CR)", location: "Cable pit surround to the western elevation of the EPP building", descriptionMaterial: "Presumed asbestos containing fibre cement", dateIdentified: "13/04/2015", siteName: "Mt Lofty", siteNo: 5018, id: 8}, 
{comments: "Label as asbestos containing material. Encapsulate exposed edges and surfaces. Consideration should be given to annual re-inspection and removal during future refurbishment works", dateRemoved: "", controlMeasure: "", riskRating: "P3", condition: "F", photoNo: "12,13", sampleNo: "NT", matrix: "B", type: "NT", location: "Pipe beneath the Community FM antenna (the pipe extended beneath ground surface in an unknown direction).", descriptionMaterial: "Presumed asbestos containing fibre cement", dateIdentified: "13/04/2015", siteName: "Mt Lofty", siteNo: 5018, id: 9}
},

/* This variable is used to pass the full row of data on the selected item to the part of the interface showing the details of the selected item. */
/* Here we are pre-selecting a row by indexing into the sample data; however, the data for the pre-selected row would typically be passed in as a *
* rule input or generated with a query. */
local!selectedEmployee,

{
a!columnsLayout(
columns: {
a!columnLayout(
contents: {
a!sectionLayout(
label: "Employees",
contents: {
a!gridField(
/* Replace the dummy data with a query, rule, or function that returns a datasubset and uses fv!pagingInfo as the paging configuration. */
data: todatasubset(local!employees,fv!pagingInfo),
columns: {
a!gridColumn(
label: "Date identified",
value: fv!row.dateIdentified
),
a!gridColumn(
label: "Material",
value: fv!row.descriptionMaterial
)
},
pageSize: 3,
selectable: true,
selectionStyle: "CHECKBOX",
selectionValue: index(local!selectedEmployee, "id", {}),
selectionSaveInto: {
/* This save replaces the value of the previously selected item with that of the newly selected item, ensuring only one item can be selected at once.*/
a!save(
local!selectedEmployee,
if(
length(fv!selectedRows) > 0,
fv!selectedRows[length(fv!selectedRows)],
null
)
),
/*a!save(local!selectedId,null)*/
},
shadeAlternateRows: false,
rowHeader: 1
)
}
)
}
) 

},
stackWhen: {
"PHONE",
"TABLET_PORTRAIT"
}
),
/*a!paragraphField(*/
/*value: index(local!selectedEmployee, "id", {})*/
/*)*/
}
)
}

  Discussion posts and replies are publicly visible

  • 0
    Certified Lead Developer

    What is the value of local!selectedEmployee after you try selecting one row?

    I believe you might want to simplify your selection code and then work from there -- iirc, your code for selectionValue might be wrong, since I believe Appian decides what rows are selected by the "identifiers" of a data subset, and if that doesn't exist (i.e. when using a straight dictionary), it falls back to a plain index of the row within the dictionary.  The IDs of your employees are {6, 7, 8, 9} but Appian is likely expecting array index (i.e. {1, 2, 3, 4}) to determine selected row.

  • Thanks for the details Mike. After testing some scenarios based on ur explanation and Appian documentation, I agree with you on this. It looks like Appian is expecting array index like {1,2,3,4}. But how do we get array index starting with 1 when we use a query rule? Id's can be any number. In that case this design pattern fails.

  • 0
    Certified Lead Developer
    in reply to ashoku

    I mentioned identifiers.  Specifically, when you use a query rule (edit: i mean a "query entity" rule, i.e. an expression rule that calls query entity preferably) to return a data subset, it returns a property called "identifiers" which the grid will then use to save and identify selected rows.

  • Hello Ashok,

    You can use below code to make the selection hold its value.

    {
    a!localVariables(

    local!employees: {

    {comments: "Consideration should be given to annual re-inspection and removal during future refurbishment works.", dateRemoved: "", controlMeasure: "", riskRating: "P4", condition: "S", photoNo: "1,2", sampleNo: "Previously Identified", matrix: "B", type: "CH,AM", location: "Underside of the awning between the Transmitter Building (Equipment Building) and EPP Building", descriptionMaterial: "Fibre cement sheeting", dateIdentified: "13/04/2015", siteName: "Mt Lofty", siteNo: 5018, id: 6},
    {comments: "Remove as soon as practicable. All ground maintenance works within the vicinity of the cable pit should be suspended immediately until removal works have been completed. If material is removed by a licenced asbestos removal contractor, a clearance inspection and subsequent clearance certificate may be required", dateRemoved: "", controlMeasure: "", riskRating: "P2", condition: "P", photoNo: "3,4", sampleNo: "GB05", matrix: "B", type: "CH,AM", location: "Cable pit surround to the north of the Transmitter Building (Equipment Building) and south of the satellite dishes", descriptionMaterial: "Fibre cement", dateIdentified: "13/04/2015", siteName: "Mt Lofty", siteNo: 5018, id: 7},
    {comments: "Remove as soon as practicable. All ground maintenance works should ve suspended immediately until removal works have been completed. If material is removed by a licenced asbestos contractor, a clearance inspection and subsequent clearance certificate may be required", dateRemoved: "", controlMeasure: "", riskRating: "P3", condition: "F", photoNo: "7,8", sampleNo: "Similar material as GB06", matrix: "B", type: "NT(CH,AM,CR)", location: "Cable pit surround to the western elevation of the EPP building", descriptionMaterial: "Presumed asbestos containing fibre cement", dateIdentified: "13/04/2015", siteName: "Mt Lofty", siteNo: 5018, id: 8},
    {comments: "Label as asbestos containing material. Encapsulate exposed edges and surfaces. Consideration should be given to annual re-inspection and removal during future refurbishment works", dateRemoved: "", controlMeasure: "", riskRating: "P3", condition: "F", photoNo: "12,13", sampleNo: "NT", matrix: "B", type: "NT", location: "Pipe beneath the Community FM antenna (the pipe extended beneath ground surface in an unknown direction).", descriptionMaterial: "Presumed asbestos containing fibre cement", dateIdentified: "13/04/2015", siteName: "Mt Lofty", siteNo: 5018, id: 9}
    },
    local!data: todatasubset(local!employees,a!pagingInfo(1,-1)),

    /* This variable is used to pass the full row of data on the selected item to the part of the interface showing the details of the selected item. */
    /* Here we are pre-selecting a row by indexing into the sample data; however, the data for the pre-selected row would typically be passed in as a *
    * rule input or generated with a query. */
    local!selectedEmployee,

    {
    a!columnsLayout(
    columns: {
    a!columnLayout(
    contents: {
    a!sectionLayout(
    label: "Employees",
    contents: {
    a!textField(value:local!data.identifiers),
    a!gridField(
    label:"data",
    data:local!data.data,
    columns :{
    a!gridColumn(
    label: "Date identified",
    value: fv!row.dateIdentified
    ),
    a!gridColumn(
    label: "Material",
    value: fv!row.descriptionMaterial
    )},
    pageSize: 3,
    selectable: true,
    selectionStyle: "CHECKBOX",
    selectionValue:local!selectedEmployee,
    selectionSaveInto: a!save(local!selectedEmployee,save!value),
    shadeAlternateRows: false,
    rowHeader: 1
    )
    }
    )
    }
    )

    },
    stackWhen: {
    "PHONE",
    "TABLET_PORTRAIT"
    }
    ),
    /*a!paragraphField(*/
    /*value: index(local!selectedEmployee, "id", {})*/
    /*)*/
    }
    )
    }

  • 0
    Appian Employee
    in reply to ashoku

    Just to clarify, are you using the Query Rule object (which has been deprecated) or an expression rule that returns a!queryEntity()? I'd highly suggest using a!queryEntity() since it will always return a datasubset with the appropriate identifiers. Also, it's generally easier to set up the grid with the query embedded directly into the data parameter, since then Appian can handle paging and will automatically determine the identifiers.

  • 0
    Certified Lead Developer
    in reply to Peter Lewis

    Sorry, i didn't mean to use the term "query rule" - i blame posting while tired & from mobile ;-)

  • I'm using expression rule which uses query entity to get the datasubset of data. The identifiers that are generated by query entity are primary keys of that table say 'id'. The selection value in the grid can only be index integer and identifiers that are generated from query entity can be any number. This is where I believe something is not right. If you can consider the design pattern 'Master detail' (listed above) and if you change the values of id  in local!employees data to say {3,4,5,6} instead of {1,2,3,4} and if you try to click on the first row, 3rd row gets highlighted coz the selection value here is 3 and this is not right.

  • 0
    Certified Lead Developer
    in reply to ashoku

    My point was, when the grid is initialized using a data subset containing identifiers, the grid uses those identifiers instead of the row indexes for selection values.  If you do a bit of testing on this, you should see what I mean.  This is also explained in the documentation for the current version of the grid field, if I remember correctly.

  •  Thanks for the details Mike. I agree that grid use identifiers instead of row indexes for selection values while using datasubset data. Lets assume the first row of data has identifier id 3 (instead of 1). So, if use the condition  index(local!data, "id", {}), the selectionvalue will be 3. So, when u click on the 1st row of grid, since the selectionValue is 3...it's highlighting 3rd row instead of 1st row. I'm not sure if i'm making any sense or if my understanding is incorrect.

  • 0
    Certified Lead Developer
    in reply to ashoku

    The value you save for selection value really just needs to be an array of identifiers.  You're making this unnecessarily complicated and it's causing confusion.

    I just quickly configured a brand new grid to test and created ri!selection as an array of integer to hold my identifiers, and the following configuration works fine for the default multi-select scenario:

    If your requirement is to only allow one selection at a time then it's easy(ish) to revise JUST the saveInto here to capture just the last value in "save!value" when it's longer than 1 item, which has the effect of only allowing one selection.

    Both of these are working fine for me in my live example.