Hello,

Is there a way to make a form variable dependent by the process that uses it?

I want to initialize a list based on the current process in order to pass it as an argument to a checkbox control. (based on options chosed previously the list should have different items).

 

pluginManager.getBean("workflowActivity") returns null in the form variable.

And from WorkflowManager I don't know how to get the current running process.

Thank you.

Edit: the original title was "Workflow Variable dependent by process", but that was a mistake, I meant to say "Form Variable" from the start but somehow mixed them up.

8 Comments

  1. Hi Vlad,

    I'm not too sure of what you're trying to achieve, but here's my take on what you're trying to do:

    For a particular process, you would like a form's checkbox options, which is based on a form variable, to feature different sets of choices, depending on what's been set by the user of a previous activity.

    Is this correct?

    1. Hello Sam,

      Exactly. Do you have any sugestions on how to achive this?

      Regards.

      1. Hi Vlad,

        I would try using a BeanShell Plugin within the Form Variable. In the code, I'd look up the Workflow Variable set in the previous activity by using Hash Variable, and by using that, and conditional processing, I will return the appropriate set of Form Variables. I've not tried this out myself, but it's just an idea. Do come back with your outcome!

        Regards,

        Sam

        1. Hi Sam,
          

          My approach is similar with the one mentioned by you: I am using the BeanShell on the form variable.

          I tried passing the hash variable, but I haven't managed to do it correctly.

          My first approach was:

          import ASI.org.components.*;
          
          return FormVariableManager.GetLocalProcessCheckList(pluginManager, "#assignment.processId#");
          


           

          This approach got me in the string variable (the second of the procedure) the value "#assignment.processId#".

          My second approach was:

          import ASI.org.components.*;
          
          return FormVariableManager.GetLocalProcessCheckList(pluginManager, #assignment.processId#);
          


          This got me an ugly exception in the console, something like "incorect syntax near #: found a ...".

          Any sugesstions on how to use the hash variable in the BeanShell?

          Thank you.

          Edit: So I am comming with some info afther inspecting the source code. Apparently in the BeanPlugin if one uses it under a FormVariable a mysterious WorkflowUtil.processVariable is called like this

          WorkflowUtil.processVariable(script, "", null);
          

          where the null represents a WorkflowAssignment object. And the parsing for a Hash Value that is like #assignment.# is made only if the WorkflowAssignment is not null.

          1. Hi Vlad and Sam,

            The Hash Variables only work in BeanShell Plugin, when the plugin is used as Application Plugin (tool), not when it's used as Form Variable Plugin, 'cos there's no assignment object in the context.

            I came to similar use case recently, and I have 2 suggestions.

            1. If the possible combinations of checkboxes set is not many, an easy way is to create all possible checkboxes sets in the form (such as type1Options, type2Options, type2Options), and use JavaScript in Custom HTML to hide all of them by default. Then, as and when the element that decides the type (such as selectbox?) changes its value (onChange), we use JavaScript again to show the relevant checkboxes set.

            The disadvantages here is, it gets ugly in the background if there are a lot of possible sets of checkbox options, and each set is using different element name.

            2. Another suggestion, is to write a JSON API yourself, which will be called by the element that decides the type (such as selectbox?). When the type is changed, and AJAX call will be initiated, to the JSON API you have written, passing in the type as parameter, to return checkbox option values. Then, based on the JSON objects returned, you can dynamically create its relevant options.

            A bit of geeky effort is needed (smile)

            1. Hi Tien Soon,

              Thanks for your feedback. I'd try option (1), and use the workflow hash variable for the setting required from the previous activity, in the Custom HTML JavaScript to decide which set of Options to show. This should be similar to the original idea, but with the exception that this will be down in the form itself in a Custom HTML field. From what I understand, Vlad needs the set of check-boxes shown only upon loading of the form and not dynamically change with content of that current form.

              Is there a way to get the Assignment in the BeanShell Plugin for individual instances? I think Vlad was trying to do that, which makes sense, so that the Form Variable can be reused by different processes.

              Thanks!

            2. Hello Tiensoon,

              Hello Sam,

              Thank you for your responses. I have analysed the possibilities, and I admit that although the second option Tiensoon mentioned was a more elegant one, I went along with a solution that is not as elegant as that one but not the ugliest one there is.

              My solution was to use workflow variables. The items that wore dependent by previous activities fit into a workflow variable (they are not so many), so I've used a tool with BeanShell to populate my workflow variable with some data and in my activity I used a customHtml element to insert some javascript that would read the workflow variable and generate the options on the web page.

              Here is the procedure that initializes the workflow variable: 

              public static void InitializeData(PluginManager pluginManager, WorkflowAssignment workflowAssignment)
               {
                FormManager formManager = (FormManager) pluginManager.getBean("formManager");
                WorkflowManager workflowManager = (WorkflowManager) pluginManager.getBean("workflowManager");
                String processId = workflowAssignment.getProcessId();
              
                Form form = formManager.loadDynamicFormByProcessId(Constants.AuditFormDataTable, processId);
                Map<String, String> formData = form.getCustomProperties();
              
                Map<String, String> selectedItems = new HashMap<String, String>();
              
                //
                // *The place where selectedItems elements are created*
                //
                // selectedItems now has a list of key/value that must be shown on the page
              
                JSONObject json = new JSONObject();
                try {
                 json.put("data", selectedItems);
                } catch (JSONException e) {
                 System.err.print(e.getMessage());
                }
                finally {
                 workflowManager.activityVariable(workflowAssignment.getActivityId(), Constants.VariabliaElementeAlese ,json.toString());
                }
              
               }
              

               And here is what Í've putted in the customHtml control:

              <script type="text/javascript">
               function addRadioElement(v, arg_value, arg_label)
               {
                formbuilderWidgetContainer = $(v).parents().get(1);
                var baseString = '<div id="{my_id}"><input {my_disabled} name="{my_name}" columnName="{my_columnName}" value="{my_value}" id="checkbox_{my_id}" variableName="{my_variable}" type="radio"/> <span>{my_label}</span></div>';
                var t = new Template(baseString);
                var val = t.run({
                 my_id: v.id,
                 my_name: v.name,
                 my_cssClass: $(v).attr('class'),
                 my_columnName: $(v).attr('columnName'),
                 my_value: arg_value,
                 my_label: arg_label,
                 my_variable: $(v).attr('variableName'),
                 my_disabled : (v.disabled) ? 'disabled="disabled"' : ''
                });
                $(formbuilderWidgetContainer).append(val);
               }
                  function formbuilderOnReady() {
                var variableName = 'ASI_wpAudit_ElementeAuditabile';
                var url = contextPath + 'web/json/workflow/process/variable/' + currentProcessId + '/' + variableName +'?rnd=' + new Date().valueOf().toString();
                $.getJSON(url, function(json){
                 if( typeof(json) != 'object' || /^Error/.test(json)){
                  alert('Incorect data!');
                  return;
                 }
              
                 var jsonArray = eval('(' + json.variableValue + ')');
              
                 $.each(eval('(' + json.variableValue + ')').data, function(key, text) {
                  addRadioElement($('*[id="_ex_radio_0_1"]')[0], key, text);
                 });
                });
              
                  }
              </script>
              
              


              It would be great if in the next versions of Joget the form variables (or any other new type of variables meant to be used as datasources for multi-option controls) would have an option to be context-dependent.

              Regards.

  2. Hi,

    I am trying to list out Department Name in my drop down list. Noted that I've also used same form variable method to call userlist in the drop down.

    1)Can anyone look at my code whether is correct or not?

    import java.util.*;
    import org.joget.directory.model.User;
    import org.joget.directory.model.dao.user.UserDao;
    import org.joget.plugin.base.PluginManager;
    import org.apache.commons.collections.SequencedHashMap;

    Map result = new SequencedHashMap();
    result.put("", "");
    UserDao userDao = (UserDao) pluginManager.getBean("userDao");
    Collection deptList = userDao.getDepartmentListByOrganization("ORG-002", null , null , null , null );
    for (Iterator it=deptList.iterator(); it.hasNext(); ) {
      Dept dept = (Dept) it.next();
      result.put(dept.getDepartmentId, "" + dept.getDepartmentName());

    }

    return result;

    2) Where can I refer collection of all API in Joget