fileUploadField saveInTo

Certified Senior Developer

Scenario: I have a created a reusable fileUploadField component which I am planning to use in all existing fileUploadField field in all apps. I have created a rule inputs for all the parameters of the fileUpload field and passing values to the common component while calling it. In saveInTo of the common component I am calling a!startProcess which will run asynchronously(i.e. no activity chaining). 

Issue: 

  1. When I drag and drop multiple documents to file upload, a!startProcess is being called multiple times. Is this behavior expected? i.e when I upload multiple docs at the same time, saveInTo will execute multiple times?
  2. Sometimes, when I upload multiple docs at the same time, getting the following error. (Especially when I upload 3 to 4 docs at the same time)

Could not display interface. Please check definition and inputs. Interface Definition: Expression evaluation error [evaluation ID = 50518:8f67a] in rule 'aco_fileuploadfield' : An error occurred while executing a save: Expression evaluation error : Attempted to run a second smart service, but only one smart service can be run per expression evaluation.

Note: I have built this functionality to capture document details across all apps and all upload fields which are already in use. We don't want to change any UI and major changes to existing screens.

  Discussion posts and replies are publicly visible

  • 0
    Certified Lead Developer

    All of this is expected behaviour. Trying to build such a generic component, especially for file uploads is a challenging task.

    At the end of this blog post, I give a short explanation of the way I do this kind of "File-upload Anywhere" component.

    https://appian.rocks/2024/05/20/file-upload-in-appian/

  • 0
    Certified Lead Developer

    What is your StartProcess call actually doing?  Are you passing in the uploaded Doc IDs?  Are you doing so one at a time, or as an array?  I would note that these would be UN-submitted doc IDs most likely, and if so they probably won't do what you want (unless you're just noting the raw numeric IDs to a DB table or something).  Can you share a code snippet of how you're constructing this call, so we don't have to guess?

  • 0
    Certified Senior Developer
    in reply to Mike Schmitt

    Hi Mike,

    I am trying to capture the Document IDs and constructing the CDT to have some other data points. And calling the process to write this data to DB.
    It is working fine when I upload single document. But when I upload multiple, saveInTo is called two times and triggering two instances.
    And also, when I upload 2 or more documents getting the below error.

    Basically, I want to capture the document IDs uploaded in all fileUploadFields. However, most of our tables don't have records and also documents are stored in numerous different tables. Also, client don't want to see any visible changes in UIs

  • 0
    Certified Lead Developer
    in reply to riyazn2499

    I don't know if I can even guess at any suggestions (even assuming anything would work around this issue) without seeing the actual code.

    Can you share a code snippet of how you're constructing this call, so we don't have to guess?
  • 0
    Certified Senior Developer
    in reply to Mike Schmitt

    a!localVariables(
      /*Contains all documents uploaded in file upload*/
      local!allUploadedDocuments: a!refreshVariable(
        value: ri!value,
        refreshOnReferencedVarChange: false
      ),
      /*Contains documents which are active in file upload field*/
      local!activeDocuments: a!refreshVariable(
        value: ri!value,
        refreshOnReferencedVarChange: false
      ),
      /*Contains all documents which needs to be deleted*/
      local!documentsToDelete,
      a!fileUploadField(
        label: ri!label,
        labelPosition: a!defaultValue(value: ri!labelPosition, default: "ABOVE"),
        instructions: ri!instructions,
        helpTooltip: ri!helpTooltip,
        target: ri!target,
        fileNames: ri!fileNames,
        fileDescriptions: ri!fileDescriptions,
        maxSelections: ri!maxSelections,
        value: local!activeDocuments,
        saveInto: {
          a!save(local!activeDocuments,save!value),
          ri!saveInto,
          a!save(
            local!allUploadedDocuments,
            reject(
              a!isNullOrEmpty(_),
              union(
                tointeger(local!activeDocuments),
                tointeger(local!allUploadedDocuments)
              )
            )
          ),
          a!save(
            local!documentsToDelete,
            difference(
              tointeger(local!allUploadedDocuments),
              tointeger(local!activeDocuments)
            )
          ),
            a!startProcess(
              processModel: cons!ACO_PM_INSERT_AND_DELETE_DOCUMENT_DETAILS,
              processParameters: {
                activeDocs: local!activeDocuments,
                deletedDocs: local!documentsToDelete,
                appID: ri!appID,
                requestID: ri!requestID,
                documentTags: ri!documentTags
              },
              onSuccess: {
                a!save(
                  local!allUploadedDocuments,
                  difference(
                    tointeger(local!allUploadedDocuments),
                    tointeger(local!documentsToDelete)
                  )
                ),
                a!save(
                  local!documentsToDelete,
                  null
                )
              }
            )
        },
        required: a!defaultValue(value: ri!required, default: false),
        requiredMessage: ri!requiredMessage,
        disabled: a!defaultValue(value: ri!disabled, default: false),
        validations: ri!validations,
        validationGroup: ri!validationGroup,
        buttonStyle: a!defaultValue(
          value: ri!buttonStyle,
          default: "SECONDARY"
        ),
        buttonSize: a!defaultValue(value: ri!buttonSize, default: "SMALL"),
        accessibilityText: ri!accessibilityText,
        showWhen: a!defaultValue(value: ri!showWhen, default: true),
        uploadMethods: ri!uploadMethods,
        buttonDisplay: ri!buttonDisplay,
        placeholder: ri!placeholder,
        showVirusScanMessage: a!defaultValue(
          value: ri!showVirusScanMessage,
          default: false
        )
      )
    )

    Above code the common component which can be called in all existing fileUploadField.

    In process model writing and deleting the data from DB.



  • 0
    Certified Lead Developer
    in reply to riyazn2499

    So I'm afraid the plain answer here is that this has grown too bloated for its own good - the File Upload Field is already not very flexible sadly, and you're trying to make it do everything all at once.  Having a single File Upload Field handle multiple files is already pretty clumsy even when the use case and implementation is strictly kept pretty simple - and i fear this is an example of what happens otherwise. 

    For better or worse I pretty much never use a multiple-enabled upload field anywhere unless i'm doing a VERY SIMPLIFIED bulk upload (and even then it's super rare).  All other times I enforce that my forms deal with a single upload at a time (or at least a single upload per instance of the upload field); often I force a "submit" click if possible (or some other commit click etc).  Either of these approaches (despite the fact that they would both violate the requisites you laid out) would likely solve the "multiple smart services" issue as the upload field attempts to loop over the newly-uploaded files and inadvertently tries to launch multiple startProcess calls.  Sadly I don't think current functionality exists to let you get around this without *some* compromise.

  • 0
    Certified Senior Developer

    Hi  , I am also facing the same issue did you find any solution to trigger process model only once?

  • 0
    Certified Lead Developer
    in reply to Narasimha Reddy

    What exactly do you mean with "same issue"?

  • 0
    Certified Senior Developer
    in reply to Stefan Helzle

    Hi  

    I am trying to change the filenames while uploading the files without submitting

    I used a!submituploadfiles function to upload documents and triggering process model in saveInto to change doc names

    when i am uploading multiple docs saveInto executing multiple times with respect to number of docs. if i upload 3 documents at a time 3 instances are getting created and throughing error as cant execute smartservice second time

  • 0
    Certified Lead Developer
    in reply to Narasimha Reddy

    You can only use a single smart service function in a saveInto. You will have to find a different way.

    BTW, why do you need to change file names?