Error passing data from process model to interface

Certified Associate Developer

I have an interface that has four dropdown components with dynamic choiceValues based on a query. When a value in the first dropdown is selected, it filters the values of the second dropdown. The second dropdown filters the third and the third dropdown filters the fourth. Each dropdown is disabled until a value is selected from each of the previous dropdowns. This works perfectly in the interface. 

However, in the process model there is an option to "edit existing equipment" that will query a database and fill in fields in the interface, possibly including the four dropdown components mentioned above. When I test this process, I get an error that seems to be telling me that a query for one of the dropdowns in the interface is returning null when it shouldn't. 

Hopefully this makes sense, please feel free to ask for clarification on anything. I have included the relevant code below. Thank you in advance for your help!

Here is the query in the interface that generates the choiceValues for the dropdown component that I'm getting the error in:

local!frameType:
  /*if(*/
    /*and(*/
      /*not(isnull(ri!manufID)),*/
      /*not(isnull(ri!Model))*/
    /*),*/
    a!queryEntity(
      entity: cons!Pump_Frame_Unique,
      query: a!query(
        selection: a!querySelection(
          columns: { a!queryColumn(field: "frametype") }
        ),
        logicalExpression: a!queryLogicalExpression(
          operator: "AND",
          filters: {
            a!queryFilter(
              field: "mfgid",
              operator: "=",
              value: ri!manufID
            ),
            a!queryFilter(
              field: "model",
              operator: "=",
              value: ri!Model
            )
          },
          ignoreFiltersWithEmptyValues: true
        ),
        pagingInfo: a!pagingInfo(
          startIndex: 1,
          batchSize: - 1,
          sort: a!sortInfo(field: "frametype", ascending: true)
        )
      ),
      fetchTotalCount: true
    ).data,
    /*null()*/
  /*),*/

choiceLabels and Values in the related dropdown component:

choiceLabels: {
                    index(local!frameType, "frametype", " "),
                    "OTHER"
                  },
                  choiceValues: {
                    index(local!frameType, "frametype", " "),
                    "OTHER"
                  },

This is the contents of the "value" field in the data tab of the user task node in the process model:

= rule!QueryExistingSurvey(
  custName: pv!Cust_Name,
  locName: pv!Loc_Name,
  equipNo: pv!editEquipNo,
  field: "frametype"
)

rule!QueryExistingSurvey:

keyval(
  a!queryEntity(
    entity: cons!application_view_report,
    query: a!query(
      selection: a!querySelection(columns: a!queryColumn(field: ri!field)),
      logicalExpression: a!queryLogicalExpression(
        operator: "AND",
        filters: {
          a!queryFilter(
            field: "customerName",
            operator: "=",
            value: ri!custName
          ),
          a!queryFilter(
            field: "locationName",
            operator: "=",
            value: ri!locName
          ),
          a!queryFilter(
            field: "equipmentId",
            operator: "=",
            value: ri!equipNo
          )
        },
        ignoreFiltersWithEmptyValues: true
      ),
      pagingInfo: a!pagingInfo(startIndex: 1, batchSize: - 1)
    ),
    fetchTotalCount: false
  ).data[1],
  ri!field,
  ":",
  "]"
)

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer

    Why are you calling keyVal() in your rule rule!QueryExistingSurvey?  It looks like you're attempting to call it on straight dictionary data returned from QueryEntity, and I would start with the assumption that keyVal() would not work because it's intended to operate on a text value.  If you're just trying to get a property from a dictionary based on a passed-in field name, you should be using the property() function instead.

    What is the result of this rule when you run it, and what data type does it end up being?

  • 0
    Certified Associate Developer
    in reply to Mike Schmitt

    I'm using keyVal to essentially replace the dot operator at the end of the query since "data.ri!field" is not valid. I use ri!field to improve the usability of the rule. When I test the rule I get the result I expect. For example, the keyVal takes "{manuf: SULZER}" and outputs "SULZER" as a text string.

    I did recently learn that the index function can also be used for this.

  • 0
    Certified Lead Developer
    in reply to Jack Ferguson

    I'd strongly encourage you to use property() instead of the way you're doing it currently.  Namely because there's no guarantee that the result from a query will continue behaving this way in the future.  Also, i'm fuzzy on this but I'd expect your rule will return a singular text value (due to keyval()), where depending on the query results we'd expect it to be an array (though i'm admittedly not as familiar with keyval() so I might be off base here).

    index() and property() are synonymous, allegedly functionally identical rules, but for code clarity (etc), my best practice is to only use index() when getting an index (array position), and use property() when getting a [dot] property.  (And yes this is a hill I'll die on, lol).

  • 0
    Certified Associate Developer
    in reply to Mike Schmitt

    Yes, as I have it configured, keyVal will only return a single text value. This is expected as each time I call the rule I should get a single text value.

  • 0
    Certified Lead Developer
    in reply to Jack Ferguson

    I know this is in-the-weeds, but if the expectation is for the query to only return one (or less) results, then you should consider passing a "batchSize" of 1 instead of -1 (since this will return every row in that table that matches your filters, and if you accidentally pass blank filters for some reason, it'll try to actually return every row).

    As far as your actual issue - i'm still pretty fuzzy on how your process is set up and how this rule ends up interacting with the form, as well as what exactly your error is (and where).

    • Would you be able to post some clarifying screenshots?
    • What is the exact error message you're getting?
    • What is the full code of your dropdown configuration?
    • What rule input is the result of rule!QueryExistingSurvey() mapped to, and what is it intended to do on your form?
  • 0
    Certified Associate Developer
    in reply to Mike Schmitt

    In the start process form the user selects a customer and location that is going to be surveyed. If equipment already exists in the database a grid will appear and display the equipment number and buttons to either edit the equipment information or remove the equipment. When the user chooses to edit the equipment the process model goes to the "Edit Equipment" node and (theoretically) whatever information we already have in the database is passed into the form and auto populates into the correct field.

    rule!QueryExistingSurvey() is mapped to the majority of the node inputs in the "Edit Equipment" node with only the "field" property changing for each input.

    Dropdown component code:

    a!dropdownField(
                      label: "Frame/Type:",
                      labelPosition: "ABOVE",
                      placeholder: "--- Select a Value ---",
                      choiceLabels: {
                        index(local!frameType, "frametype", " "),
                        "OTHER"
                      },
                      choiceValues: {
                        index(local!frameType, "frametype", " "),
                        "OTHER"
                      },
                      value: ri!Type,
                      saveInto: {ri!Type,
                        a!save(
                          ri!SBType,
                          null()
                        )  
                      },
                      searchDisplay: "AUTO",
                      showWhen: and(
                        not(ri!Manuf = "OTHER"),
                        not(ri!Model = "OTHER")
                      ),
                      disabled: if(
                        and(
                          not(isnull(ri!Manuf)),
                          not(isnull(ri!Model))
                        ),
                        false(),
                        true()
                      ),
                      validations: {}
                    ),

    Overall process model:   (the "Edit Equipment" node is where I'm having problems)

    Data tab of the "Edit Equipment" node: (the value is the QueryExistingSurvey rule whose code is in the original question)

    Pre Survey Form (edit button is pencil icon):

    Error message: (when attempting to edit P-10502)

  • +1
    Certified Lead Developer
    in reply to Jack Ferguson
    rule!QueryExistingSurvey() is mapped to the majority of the node inputs in the "Edit Equipment" node with only the "field" property changing for each input.

    Why are you doing this?  The overall effect is that you'll be repeating the same query over and over again just to pull a different field from each run.  Unless I'm missing something, a much better way (and the standard way) would be to handle this in local variables on your task form itself.  For one thing, that makes it substantially easier to troubleshoot.  And then of course, it means you only need to run the query once, saving the result into a local variable, then (if needed) create local variables where you pull out the property for each "field" type you need.

  • 0
    Certified Associate Developer
    in reply to Mike Schmitt

    You are right, that is absolutely a better way to do that. I think I got this form mixed up in my head with another form that needs to be available offline, in which case querying within the form wouldn't work. I do have a form in this application that needs to be offline capable and have the same information passed into it, however I think I came up with a much better solution for that over the weekend.

    Thanks for your help Mike.

Reply
  • 0
    Certified Associate Developer
    in reply to Mike Schmitt

    You are right, that is absolutely a better way to do that. I think I got this form mixed up in my head with another form that needs to be available offline, in which case querying within the form wouldn't work. I do have a form in this application that needs to be offline capable and have the same information passed into it, however I think I came up with a much better solution for that over the weekend.

    Thanks for your help Mike.

Children
No Data