How to display multiple files with document link in a single column

Hi,

I have a grid style interface based on process backed record. One of the column(Documents) has multiple files. See the screenshot below:

I'm trying to display download link for the docs listed. I am getting error "Could not display interface. Please check definition and inputs.
Interface Definition: Expression evaluation error at function a!forEach [line 358]: Error in a!forEach() expression during iteration 1: Expression evaluation error at function 'document' [line 361]: The passed parameter(s) are of the wrong type. Received the type List of Document."

Here is the code:

a!gridTextColumn(
            label: "Documents",
            field: "documentAttachmentArray",
            data: if(local!datasubset.totalCount=0,{},a!forEach(items: local!datasubset.data,
                  expression: joinarray(index(fv!item, "documentAttachmentArray", {}),"; "))),
            links: a!forEach(
                   items: local!datasubset.data,
                   expression: joinarray(a!documentDownloadLink(
                              label: document(index(fv!item, "documentAttachmentArray", {}),"name"),
                              document: index(fv!item, "documentAttachmentArray", {})
                ),"; ")
                   )
          )

Any help is appreciated.

Thanks,

Meena

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer

    Can you confirm what version of Appian you're on?  Hopefully it's 19.2+ as subhad previously mentioned as it would be a very preferable option for you to convert your grid to the 19.2 version (your current code is still using the old a!gridTextColumn() rule which goes with the older style grid, so either way some conversion would be necessary).

  • Thanks for your suggestions. Tried to use document viewer component but looks like it is not available in 18.2.  Also, we are trying to modernize the application which is portal based and users are used of all these behaviors for years and any change is very tough to get support. But we are constantly trying. They already get docs in email but these are part of customized process dashboard where they get summary and also access to docs which is convenient for Contracting officers since they deal with several contracts and don't want to look through their email unless they are working on a particular one.

    What other methods other than editable grid work in 18.2?

    Thanks,

    Meena

  • 0
    Certified Lead Developer
    in reply to meenakshir

    The only other option I can think of is to split out to 2 columns, one for each document you'd like to link, as I mentioned above - did you consider this method?  It would be fairly easy at least.

  • How do i get to each of the docs in documentAttachmentArray in the paging grid and display it in a separate column? 

    Thanks for your help!

      a!gridTextColumn(
                label: "Date Approved",
                field: "OMCAppointmentInfo.AppointeeOM.DateApproved",
                data: if(local!datasubset.totalCount=0,{},index(index(local!datasubset.data.OMCAppointmentInfo,"AppointeeOM",{}),
                     "DateApproved",{}
                      ))
              ),
              a!gridTextColumn(
                label: "Date Removed",
                field: "OMCAppointmentInfo.AppointeeOM.DateRemoved",
                data: if(local!datasubset.totalCount=0,{},index(index(local!datasubset.data.OMCAppointmentInfo,"AppointeeOM",{}),
                     "DateRemoved",{}
                      ))
              ),
              a!gridTextColumn(
                label: "Documents",
                field: "documentAttachmentArray",
                data: if(local!datasubset.totalCount=0,{},a!forEach(items: local!datasubset.data,
                      expression: joinarray(rule!OMC_getDocNames(index(fv!item, "documentAttachmentArray", {})),"; "))),
                links: a!forEach(items: local!datasubset.data,
                                 expression: rule!OMC_getDocLinks(index(fv!item, "documentAttachmentArray", {}))
                      )
                     
              ),
              a!gridTextColumn(
                label: "Appointment Status",
                field: "status",
                data: if(local!datasubset.totalCount=0,{},index(local!datasubset.data,"status",{}))
              ),

  • 0
    Certified Lead Developer
    in reply to meenakshir

    Try this.

    a!gridTextColumn(
      label: "Date Approved",
      field: "OMCAppointmentInfo.AppointeeOM.DateApproved",
      data: if(
        local!datasubset.totalCount=0,
        {},
        property(property(local!datasubset.data.OMCAppointmentInfo, "AppointeeOM",{}), "DateApproved",{})
      )
    ),
    a!gridTextColumn(
      label: "Date Removed",
      field: "OMCAppointmentInfo.AppointeeOM.DateRemoved",
      data: if(
        local!datasubset.totalCount=0,
        {},
        property(property(local!datasubset.data.OMCAppointmentInfo, "AppointeeOM",{}),  "DateRemoved",{}  )
      )
    ),
    a!gridTextColumn(
      label: "Document 1",
      field: "documentAttachmentArray",
      data: if(
        local!datasubset.totalCount=0,
        {},
        a!forEach(
          items: local!datasubset.data,
          expression: 
          /*joinarray(*/
          rule!OMC_getDocNames(
            index(
              property(fv!item, "documentAttachmentArray", {})
              1, /* return document array index 1 */
              null()
            )
          ),
          /*"; "*/
          /*)*/
        )
      ),
      links: a!forEach(
        items: local!datasubset.data,
        expression: rule!OMC_getDocLinks(
          index(
            property(fv!item, "documentAttachmentArray", {}),
            1, /* get link for 1st document */
            null()
          )
        )
      )
    ),
    a!gridTextColumn(
      label: "Document 2",
      field: "documentAttachmentArray",
      data: if(
        local!datasubset.totalCount=0,
        {},
        a!forEach(
          items: local!datasubset.data,
          expression: 
          /*joinarray(*/
          rule!OMC_getDocNames(
            index(
              property(fv!item, "documentAttachmentArray", {})
              2, /* return document array index 2 */
              null()
            )
          ),
          /*"; "*/
          /*)*/
        )
      ),
      links: a!forEach(
        items: local!datasubset.data,
        expression: rule!OMC_getDocLinks(
          index(
            property(fv!item, "documentAttachmentArray", {}),
            2, /* get link for 2nd document */
            null()
          )
        )
      )
    ),
    a!gridTextColumn(
      label: "Appointment Status",
      field: "status",
      data: if(
        local!datasubset.totalCount=0,
        {},
        property(local!datasubset.data,"status",{})
      )
    ),

    I've done 3 things here:

    1) split out the link column to 2 columns, each of which gets the name and link for one of two documents in the array, assuming there are only 2 (and it might need there to always be 2, though it should handle 1 or 0 documents with proper tweaking to null checks)

    2) replaced all your "index()" calls with "property()", which helps with code readability for getting CDT properties, particularly since I had to use "index()" to get array index values for your documents, and nesting index() functions on top of each other with different usages gets crazy to read

    3) adjusted your formatting some.

    A final note: as an aside, I see all of your columns have "if(local!datasubset.totalCount=0,{}" qualifiers, but this shouldn't be needed in the case of an empty set because when empty, your index (property) statements already return the empty set ("{}") correctly.  So removing these could help simplify your code a bit if you care to do that... but it won't help or hurt your current use case.

  • 0
    Certified Lead Developer
    in reply to Mike Schmitt

    Here's the same code but with the additional code cleanup I mentioned above:

    a!gridTextColumn(
      label: "Date Approved",
      field: "OMCAppointmentInfo.AppointeeOM.DateApproved",
      data: property(property(local!datasubset.data.OMCAppointmentInfo, "AppointeeOM",{}), "DateApproved",{})
    ),
    a!gridTextColumn(
      label: "Date Removed",
      field: "OMCAppointmentInfo.AppointeeOM.DateRemoved",
      data: property(property(local!datasubset.data.OMCAppointmentInfo, "AppointeeOM",{}),  "DateRemoved",{}  )
    ),
    a!gridTextColumn(
      label: "Document 1",
      field: "documentAttachmentArray",
      data: a!forEach(
        items: local!datasubset.data,
        expression: rule!OMC_getDocNames(
          index(
            property(fv!item, "documentAttachmentArray", {})
            1, /* return document array index 1 */
            null()
          )
        ),
      ),
      links: a!forEach(
        items: local!datasubset.data,
        expression: rule!OMC_getDocLinks(
          index(
            property(fv!item, "documentAttachmentArray", {}),
            1, /* get link for 1st document */
            null()
          )
        )
      )
    ),
    a!gridTextColumn(
      label: "Document 2",
      field: "documentAttachmentArray",
      data: a!forEach(
        items: local!datasubset.data,
        expression: 
        rule!OMC_getDocNames(
          index(
            property(fv!item, "documentAttachmentArray", {})
            2, /* return document array index 2 */
            null()
          )
        ),
      ),
      links: a!forEach(
        items: local!datasubset.data,
        expression: rule!OMC_getDocLinks(
          index(
            property(fv!item, "documentAttachmentArray", {}),
            2, /* get link for 1st document */
            null()
          )
        )
      )
    ),
    a!gridTextColumn(
      label: "Appointment Status",
      field: "status",
      data: property(local!datasubset.data,"status",{})
    ),

  • Thanks Mike for the solution. I noted somes issues. For rows with no documents , it still lists docs(possibly from other rows) and no matter what i check (count, nulls etc.,) for , i see this  even though there are no docs. Also, docs displayed are not for the corresponding rows. May be some index is messed up. Any thoughts? 

    Thanks,

    Meena

  • 0
    Certified Lead Developer
    in reply to meenakshir

    Can you share the current state of your code perhaps just for those two columns?  I'm familiar with what causes this -- basically, we would need to make sure the grid receives a "null" for each blank entry, instead of empty set, because when the grid sees an empty set it will try to fill that cell with the next valid value in the array, causing row mismatching.  I can try to provide something that gets around this but would need to work from your latest version.  Just these two columns should be sufficient.

  • Thanks for your help. Here it is. Depending on the stage of the appointment, we have either 0/1/2 docs. 

      a!gridTextColumn(
                label: "Documents",
                field: "documentAttachmentArray",
                data: if(local!datasubset.totalCount=0,{},a!forEach(items: local!datasubset.data,
                      expression: joinarray(rule!OMC_getDocNames(index(fv!item, "documentAttachmentArray", {})),"; "))
                
                      )   
      ),
      a!gridTextColumn(
                label: "Cover Letter",
                field: "documentAttachmentArray",
                data: if(local!datasubset.totalCount=0,{},a!forEach(items: local!datasubset.data,
                      expression: rule!OMC_getDocNames(index(property(fv!item, "documentAttachmentArray", {}),1,{})))),
                links: a!forEach(items: local!datasubset.data,
                                 expression: rule!OMC_getDocLinks(index(property(fv!item, "documentAttachmentArray", {}),1,{}))
                      )
                     
      ),
      a!gridTextColumn(
                label: "Memo",
                field: "documentAttachmentArray",
                data: if(local!datasubset.totalCount=0,{},a!forEach(items: local!datasubset.data,
                      expression: rule!OMC_getDocNames(index(property(fv!item, "documentAttachmentArray", {}),2,{})))),
                links: a!forEach(items: local!datasubset.data,
                                 expression: rule!OMC_getDocLinks(index(property(fv!item, "documentAttachmentArray", {}),2,{}))
                      )
                     
      )

  • +1
    Certified Lead Developer
    in reply to meenakshir

    A few things:

    1) In my previous example, I made sure the index() calls returned "null" when no data was found, instead of an empty set.  This is important.

    2) I strongly encourage you to not over-compress your code (i.e. removing so many newlines), it makes it nearly impossible to read and make sense of, either as a third party, or in my experience, if i come back some time later even to my own code.

    Please try this version and let me know if it seems to address the link issues.  The intent is that rows without the target document will get a blank label (and link) for that document instead of "stealing" the document from the subsequent row.

    a!gridTextColumn(
      label: "Documents",
      field: "documentAttachmentArray",
      data: if(
        local!datasubset.totalCount=0,
        {},
        a!forEach(
          items: local!datasubset.data,
          expression: joinarray(rule!OMC_getDocNames(index(fv!item, "documentAttachmentArray", {})),"; ")
        )
      )   
    ),
    a!gridTextColumn(
      label: "Cover Letter",
      /*field: "documentAttachmentArray",*/
      data: if(
        local!datasubset.totalCount=0,
        {},
        a!forEach(
          items: local!datasubset.data,
          expression: rule!OMC_getDocNames(
            index(
              property(fv!item, "documentAttachmentArray", {}),
              1,
              null()  /* This needs to be "null" instead of "empty set" to work */
            )
          )
        )
      ),
      links: if(
        local!datasubset.totalCount=0,
        {},
        a!forEach(
          items: local!datasubset.data,
          expression: rule!OMC_getDocLinks(
            index(
              property(fv!item, "documentAttachmentArray", {}),
              1,
              null()  /* This needs to be "null" instead of "empty set" to work */
            )
          )
        )
      )
    ),
    a!gridTextColumn(
      label: "Memo",
      /*field: "documentAttachmentArray",*/
      data: if(
        local!datasubset.totalCount=0,
        {},
        a!forEach(
          items: local!datasubset.data,
          expression: rule!OMC_getDocNames(
            index(
              property(fv!item, "documentAttachmentArray", {}),
              2,
              null()  /* This needs to be "null" instead of "empty set" to work */
            )
          )
        )
      ),
      links: if(
        local!datasubset.totalCount=0,
        {},
        a!forEach(
          items: local!datasubset.data,
          expression: rule!OMC_getDocLinks(
            index(
              property(fv!item, "documentAttachmentArray", {}),
              2,
              null()  /* This needs to be "null" instead of "empty set" to work */
            )
          )
        )
      )
    )

  • 0
    Certified Lead Developer
    in reply to meenakshir

    As a side note, the 19.2+ grid makes this literally 10 times easier.  At least.  I hope you'll let your organization know about all the wasted development time that's occurring at the moment, based solely on their need to use an outdated Appian version.  (I know it's an uphill battle sometimes - i'm just frustrated on your behalf.)

Reply Children
No Data