Trying to set a default value in a Custom Data Type which will load in a DropDown Box for a Process Start Form.

Hey Appian Community!

First time post, please forgive my newbness! Slight smile

Trying to set a default value in a Process Start Form which will essentially save the user having to select a default value when the screen loads. 

I was able to do it when I use a "User Input Task" because the UI allows to set variables of CDT types in the DATA>INPUTS window.

However when using 'Process Start Form' in the Process Modeler there's no 'INPUTS' box. There is a 'Variables' tab however it doesn't allow the user to set a variable within a nested type. I can however set values for process variables with native types such as 'integer' 'text' but not a custom data type.

Any insights would be greatly appreciated.

  Discussion posts and replies are publicly visible

Parents
  • 0
    Certified Lead Developer

    You can't do this via the process model for use with a start form - when the user is seeing a start form, no instance of the process even exists yet -- the way you should think of it is, the *results* of a successfully submitted start form are then passed into a new process instance at time of submission.

    To handle this you'll need to do it on your SAIL form itself.  There are various techniques and none of them are perfect, but many that will at least do what you want.  The one you choose depends largely on whether any subsequent form inputs or choices depend at all on the value of the selection you want to show a default version for. 

    • If there isn't anything on the form that depends on it, then you can simply make the selection field in question check for a null value and display your default selection when null, then in the SaveInto section of the Submit button, you would need to save the default value desired (if the original value is still null) into the proper field within the CDT in the Rule Inputs.
    • An alternative approach is to define a local variable with the CDT's type, where you can manually set the value up-front for the field in question to whatever your preferred default value is; then subsequent fields in the form would also save their changes into this local variable; and then on the Submit button you would save the whole local variable into the relevant Rule Input.
Reply
  • 0
    Certified Lead Developer

    You can't do this via the process model for use with a start form - when the user is seeing a start form, no instance of the process even exists yet -- the way you should think of it is, the *results* of a successfully submitted start form are then passed into a new process instance at time of submission.

    To handle this you'll need to do it on your SAIL form itself.  There are various techniques and none of them are perfect, but many that will at least do what you want.  The one you choose depends largely on whether any subsequent form inputs or choices depend at all on the value of the selection you want to show a default version for. 

    • If there isn't anything on the form that depends on it, then you can simply make the selection field in question check for a null value and display your default selection when null, then in the SaveInto section of the Submit button, you would need to save the default value desired (if the original value is still null) into the proper field within the CDT in the Rule Inputs.
    • An alternative approach is to define a local variable with the CDT's type, where you can manually set the value up-front for the field in question to whatever your preferred default value is; then subsequent fields in the form would also save their changes into this local variable; and then on the Submit button you would save the whole local variable into the relevant Rule Input.
Children
  • Hey Mike,

    Thanks for responding so quickly. 

    For point 1: So for the value should I use an expression, something along the lines of:

    If (null) then show "default_value".

    Then in the SaveInto (in Submit) do the same?

    If (null) then show "default_value".

    For Point 2: The variable is essentially a text type in the CDT. So should I pass a local Process variable (with the default value) into the form and then set that value in the form? 

    I don't quite understand what you mean by subsequent fields would also save their changes. 

     

    Appreciate your response! Cheers!

  • 0
    Certified Lead Developer
    in reply to LTSmash

    Please note (in case I wasn't clear originally) that my 2 bullet points above are mutually exclusive solutions.  It's just one or the other.

    For point 1, yes you basically have it - you would show the default value in the field on the form, but the CDT rule input would *not* contain this default value unless through manual user interaction, so during form submission, you would check whether this value is blank and if so, save the desired default value into it at that point.

    For point 2: you're confusing "local variable" with "process variable" which are completely separate things.  On a start form you do not have process variables in the equation - all it sees are local variables declared in your SAIL form, and rule input variables.  Nothing in the process model comes into play until the form is submitted.  So what I was describing, is that you would define a local variable within your form itself, to hold the contents you eventually intend to pass into your process instance (i.e. your CDT_Bikes pv).  All fields of your form would save their values into this local variable instead of into the rule input, and then you would save the whole local variable directly into the Rule Input when submitting the form.

    Take this mini example of case 2:

    a!localVariables(
      
      local!bikes: {
        id: null(),
        numWheels: 2,
        bodyType: null()
      },
      
      a!formLayout(
        label: "Add Bike",
        contents: {
          a!dropdownField(
            label: "Number of Wheels",
            placeholderLabel: "--select wheel count--",
            choiceValues: {2, 3},
            choiceLabels: {"two", "three"},
            value: local!bikes.numWheels,
            saveInto: local!bikes.numWheels
          ),
          a!textField(
            label: "Body Type",
            value: local!bikes.bodyType,
            saveInto: local!bikes.bodyType,
            required: true()
          )
        },
        buttons: a!buttonLayout(
          primaryButtons: {
            a!buttonWidget(
              submit: true(),
              label: "Submit",
              saveInto: {
                a!save(
                  ri!bikes,
                  local!bikes
                )
              }
            )
          }
        )
      )
    )

  • Hey Mike!

    As I'm learning, I want to be able to try and test both examples. For the first one I'm now receiving a new error.

    Not sure what I've done wrong here. Is it tripping up on the Constant - not sure why that wouldn't work right as it exists in the interface.

  • +1
    Certified Lead Developer
    in reply to LTSmash
    1. "placeholder label" is the default text readout (to serve as a prompt to the user) that will render in a dropdown when no value is selected - i usually put something like "--choose a condition--".  You've set it to "New" which is just one of the conditions, which is not the intent of this setting.
      1. I think for this you mistook what I was trying to say.  You would actually set the value parameter to an expression which conditionally checks the nullicity of the target ri!CDT_bikes.condition and uses the value of "New" when it's null.  In your top screenshot the target for this would be the "selected value" configuraton field, which you'd need to fill with an expression.
      2. as a side note, I strongly urge you to get used to looking at the "expression mode" code, because after the skeleton framework of your interface is set up initially, editing the code directly is easier by far.
    2. for the second version, your code is missing the required a!save() command which is the only thing that actually causes a custom save to be executed.  For brevity I'll just try to write what I think your code should be:
      if(
        isnull(ri!LTPD_CDT_Bikes.condition),
        a!save(
          ri!LTPD_CDT_Bikes.condition, /* <---- this is the save target */
          cons!LTPD_CONS_CONDITION_BIKE[1] /* <---- this is the save VALUE */
        ),
        {}  /* <---- if bikes.condition was NOT null, then we do NOT want to execute a save here. */
      )
  • Amazing, thank-you Mike.

    Got the first method going by doing just as you said. For the folks watching at home:

    - Used an IF Statement in the 'value' checking for NULL for the drop down field

    - Used an IF Statement in the Save Into checking for NULL and saving the variable. 

    PS: Getting more accustomed to the 'expression mode' definitely is easier once you know the domain names. Will be trying out the local variable method now.

  • Also got the local variable going. Thanks again Mike, legend!

    Is it normal to have to wrap the whole formLayout code into the local variables domain/function - is that best practice?

  • 0
    Certified Lead Developer
    in reply to LTSmash
    Is it normal to have to wrap the whole formLayout code into the local variables domain/function

    Yes, that's exactly how it works.  You can also wrap individual components/sections/etc in their own localvariables call, for variables that will only be used in the scope of that section/etc.  These can be nested as needed, though the easiest way to manage variables for a general use case is to have at least one at the top level of the form.  When I start a new form I usually include the wrapper at the top level even if I don't need any yet, under the assumption that I eventually will.