Is it possible to output multiple document links with a!documentDownloadLink, wi

Is it possible to output multiple document links with a!documentDownloadLink, within a!linkField, that display on the same line? Or any other solution for document links would work as well.. Similar to how joinarray(links,", ") would separate an array into a comma delmited output on the same line. My code is below, but I can't seem to creat anything that does not display links on one line each.

a!linkField(
links:
          apply(
           a!documentDownloadLink,
           merge(
                    local!docs,
                    local!docNames
           )
          )
)

OriginalPostID-165099

OriginalPostID-165099

  Discussion posts and replies are publicly visible

  • 0
    Certified Lead Developer
    I think you might be stuck with links on separate lines; AFAIK this is the default and probably only behavior. You might have some luck, though, utilizing grid functionality in some unconventional way, if you're willing to do the legwork to figure out how to code it.
  • 0
    Certified Associate Developer
    Hi csteward,
    It is not possible to display those download links on a single line, since that is not the default behaviour of that SAIL component. I think there should be some workaround for that.
  • You can use a richTextDisplayField to do that. Check forum.appian.com/.../SAIL_Components.html for inspiration.
  • 0
    Certified Lead Developer
    @Stefan: that's a good idea too - I'll need to play with RTDFs a bit more if this is one of the things that's possible with them. The best I could think of (above) was like having the individual links in separate cells in a grid, with dynamic columns depending on how many links are needed.
  • Some example code

    a!richTextDisplayField(
    value: {
    a!richTextItem(
    text: "Link to Google",
    link: a!safeLink(
    uri: "www.google.com"
    )
    ),
    a!richTextItem(
    text: " | "
    ),
    a!richTextItem(
    text: "Link to LinkedIn",
    link: a!safeLink(
    uri: "www.linkedin.com"
    )
    )
    }
    )
  • Thanks guys - Rich Text field looks to be the right direction, only issue now is getting a separator between the documents - otherwise this does display them on one line:

    a!richTextDisplayField(
    value: a!applycomponents(
    function: a!richTextItem(
    text: _,
    link: _
    ),
    array: merge(
    local!docNames,
    apply(
    a!documentDownloadLink,
    merge(
    local!docs,
    local!docNames
    )
    )
    )
    )
    )
  • You can wrap the richTextItem in a custom expression and add a separator in that. Something like

    a!richTextItem(
    text: document(ri!doc, "name") & " | ", <---- The separator
    link: a!documentDownloadLink(
    ri!doc,
    document(ri!doc, "name")
    )
    )
  • 0
    Certified Lead Developer
    And maybe it would work to have the custom expression judge whether it needs to add a separator (skipping the separator for the last in a list), and do it as a separate component so it's not hyperlinked? disclaimer: i'm not guaranteeing the following component will work right, but this is roughly what i'm thinking of:

    {
    a!richTextItem(
    text: ri!docNames[ri!index],
    link: a!documentDownloadLink(
    ri!docs[ri!index],
    ri!docNames[ri!index]
    )
    ),
    if(
    ri!index < length(ri!docs),
    a!richTextItem(
    text: " | "
    ),
    {}
    )
    }

    Note that for this example, you'd pass in the full arrays of local!docs and local!docNames, as well as an integer array for index (e.g. enumerate(length(local!docs))+1).
  • As I was thinking on a similar strategy, I was able to get this working today by wrapping the Rich Text field in an applyComponents() call, and utilizing a few helper functions. This rule will now take in a single folder ID and display all documents in one line with a nice text separator - should be great for entity backed records with attachment folder IDs stored in the DB. Essentially the expressions create arrays of documents and names, insert null values every other slot then iterate through creating either a rich text component of documentDownloadLink (where a document exists), or the text separator " | " where there is no document. I use a helper array there since null document values are a hassle, but this can probably be simplified. The rule also allows optional parameters for singleLine (display), recursiveSearch, noDocDisplayMessage and separatorText.

    load(
    local!singleLine: if(isnull(ri!singleLine),true(),ri!singleLine),
    local!recursiveSearch: if(isnull(ri!recursiveSearch),false(),ri!recursiveSearch),
    local!separatorText: if(isnull(ri!separatorText)," | ",ri!separatorText),
    local!noDocFoundMessage: if(isnull(ri!noDocFoundMessage),"No documents found",ri!noDocFoundMessage),
    local!docs: getdocumentsfromfolder(ri!folderId,local!recursiveSearch),
    local!noDocs: or(isnull(local!docs),length(local!docs)=0),
    local!docNames: if(local!noDocs,null,apply(fn!document,local!docs,"name")),
    local!docs2: if(local!noDocs,null,rdrop(
    split(
    joinarray(
    apply(
    rule!docDisplay_Insert,
    local!docs,
    2,
    0
    ),
    ","
    ),
    ","
    ),
    1
    )
    ),
    local!docNames2: if(local!noDocs,null,rdrop(
    split(
    joinarray(
    apply(
    rule!docDisplay_Insert,
    local!docNames,
    2,
    0
    ),
    ","
    ),
    ","
    ),
    1
    )
    ),
    local!which: if(local!noDocs,null,rdrop(
    split(
    joinarray(
    apply(
    rule!docDisplay_Insert,
    {
    rule!CreateArrayFromSingleValue(1,length(local!docNames))
    },
    2,
    0
    ),
    ","
    ),
    ","
    ),
    1
    )
    ),

    if(local!noDocs,
    a!richTextDisplayField(
    value: a!richTextItem(
    text: local!noDocFoundMessage/*,
    style: "STRONG"*/
    )
    ),

    if(not(local!singleLine),
    a!linkField(
    links: apply(
    a!documentDownloadLink,
    merge(
    local!docs,
    local!docNames
    )
    )
    ),
    a!richTextDisplayField(
    value: a!applyComponents(
    function: rule!docRichTextComponents(
    docName: _,
    doc: _,
    which: _,
    separatorText: _
    ),
    array: merge(
    local!docNames2,
    local!docs2,
    local!which,
    rule!CreateArrayFromSingleValue(local!separatorText,length(docs2))
    )
    )
    )
    )
    )
    )

    Helper function rule!docRichTextComponents:

    if(
    ri!which = 0,
    a!richTextItem(
    text: ri!separatorText
    ),
    a!richTextItem(
    text: ri!docName,
    link: a!documentDownloadLink(ri!doc,ri!docName)
    )
    )

    Helper function rule!docDisplay_Insert:

    =insert(ri!array,ri!value,ri!insertAt)

    Helper function rule!createArrayFromSingleValue

    =split(ri!SingleValue & rept("(*)"&ri!SingleValue,max(0,ri!DesiredLength-1)),"(*)")

  • Note the function does not error gracefully if a folder ID does not exist, but it works fine if there is a valid folder ID with no docs in it.

    Test Interface:

    = load(
    local!folderId: 42417,
    a!sectionLayout(
    label: "Documents",
    firstColumnContents: {
    rule!displayDocsFromFolder(
    folderId: local!folderId
    )
    },
    secondColumnContents: {}
    )
    )