Select a selectbox's value based on another selectbox's value


#1

Hi,

I put a new selectbox on the properties panel if a service task is selected, called Template.
The user can select from its values and up to this point everything works fine.
Now I want to preselect an option from the Implementation selectbox if the user chooses an element from the Template selectbox. To simplify the problem let’s say no matter what option the user choose from the Template box the Delegate Expression should be preselected from the Implementation box.
I have extended the CamundaPropertiesPanel if that matters and here is a snippet if that helps:

var serviceList = [{ serviceImplementation: 'Key 1', title: 'Test 1'}, {serviceImplementation: 'Key 2', title: 'Test 2'}];

function getServiceListOptions(serviceList) {
  var options = [];
  if (!serviceList || !serviceList.length) {
    return options;
  }
  for (var i = 0; i < serviceList.length; ++i) {
    options[i] = {
      name: serviceList[i].title,
      value: serviceList[i].serviceImplementation
    };
  }
  return options;
}

var DEFAULT_PROPS = {
  calledElement: undefined,
  'servicecallref': 'DELEGATEEXPRESSION'
};

function createServiceListEntry(entries, serviceImplementationEntry) {
  entries.unshift(entryFactory.selectBox({
    id: 'template',
    label: 'Template',
    selectOptions: getServiceListOptions(serviceList),
    emptyParameter: true,
    modelProperty: 'servicecallref',

    get: function(element, node) {
      return serviceImplementationEntry.get(element, node);
    },
    set: function(element, values, node) {
      var props = assign({}, DEFAULT_PROPS);
      return cmdHelper.updateProperties(element, props);
    }
  }));

  return entries;
}

function MyPropertiesProvider(eventBus, bpmnFactory, elementRegistry, elementTemplates) {
  var camundaProvider = new CamundaPropertiesProvider(eventBus, bpmnFactory, elementRegistry, elementTemplates, translate);
  PropertiesActivator.call(this, eventBus);
  this.getTabs = function(element) {
      var tabs = camundaProvider.getTabs(element);
      var generalTabIndex = tabs.findIndex(function(e) { return e.id === 'general'; });
      var detailsTabIndex = tabs[generalTabIndex].groups.findIndex(function(e) { return e.id === 'details'; });
      var entries = tabs[generalTabIndex].groups[detailsTabIndex].entries;

      var serviceImplementationIndex = entries.findIndex(function(e) { return e.id === 'implementation'; });

      if (serviceImplementationIndex >= 0) {
        createServiceListEntry(entries, entries[serviceImplementationIndex]);
        return tabs;
      }
      return tabs;
  };
}

Keep in mind that at the end I should serialize everything to XML.


#2

You would need to pre-set the implementation value once the user selects from the template select box, right?

This way, once the select box is rendered, it will automatically have the corresponding entry pre-selected.


#3

Yes @nikku. Thank you.


#4

Okay I solved my main issue. In the createServiceListEntry function the set method was never called. This was because inside the getServiceListOptions function in the name/value object array the values were not distinct. They were the same. I should thought this before. Now the set and get methods are called just fine. Regarding the rest of my question, to select a selectbox’s value based on another one I should be able to solve, but of course every help is appreciated. I will write later with the full solution.


#5

I solved my entire issue. The key was to check the XML that is saved when I select something from the Implementation selectbox. In the XML I saw in these situations a camunda:delegateExpression attribute is added with some value. The value is what you enter as Delegate Expression if you choose Delegate Expression from the Implementation selectbox. Filling something in this attribute or set it to undefined preselect the Implementation selectbox and also fulfill the Delegate Expression inputText. Of course I needed a custom descriptor to be able to serialize my Template selectbox option but that not relevant here. cmdHelper.updateBusinessObject was also needed to update the business object and the diagram(I guess, but I am not sure yet). So basically thats it, use, enjoy.

var serviceList = [{ serviceImplementation: 'Key 1', title: 'Test 1'}, {serviceImplementation: 'Key 2', title: 'Test 2'}];

function getServiceListOptions(serviceList) {
  var options = [];
  if (!serviceList || !serviceList.length) {
    return options;
  }
  for (var i = 0; i < serviceList.length; ++i) {
    options[i] = {
      name: serviceList[i].title,
      value: serviceList[i].serviceImplementation + i //this is to have unique values only
    };
  }
  return options;
}

function createServiceListEntry(entries, serviceImplementationEntry) {
  entries.unshift(entryFactory.selectBox({
    id: 'template',
    label: 'Template',
    selectOptions: getServiceListOptions(serviceList),
    emptyParameter: true,
    modelProperty: 'servicecallref',

    get: function(element, node) {
      var bo = getBusinessObject(element);
      return { resultVariable: bo.get('servicecallref') };
    },
    set: function(element, values, node) {
      var bo = getBusinessObject(element);
      var servicecallref = values.servicecallref || undefined;
      if (typeof servicecallref !== 'undefined') { // if we choose not the empty option in the Implementation selectbox
        var props = {
          'camunda:delegateExpression': 'something'
        };
      } else {
        var props = {
          'camunda:delegateExpression': undefined
        };
      }
      var props = assign({'servicecallref': servicecallref}, props);
      var commands = [];
      commands.push(cmdHelper.updateBusinessObject(element, bo, props));
      return commands;
    }
  }));

  return entries;
}

function MyPropertiesProvider(eventBus, bpmnFactory, elementRegistry, elementTemplates) {
  var camundaProvider = new CamundaPropertiesProvider(eventBus, bpmnFactory, elementRegistry, elementTemplates, translate);
  PropertiesActivator.call(this, eventBus);
  this.getTabs = function(element) {
      var tabs = camundaProvider.getTabs(element);
      var generalTabIndex = tabs.findIndex(function(e) { return e.id === 'general'; });
      var detailsTabIndex = tabs[generalTabIndex].groups.findIndex(function(e) { return e.id === 'details'; });
      var entries = tabs[generalTabIndex].groups[detailsTabIndex].entries;

      var serviceImplementationIndex = entries.findIndex(function(e) { return e.id === 'implementation'; });

      if (serviceImplementationIndex >= 0) {
        createServiceListEntry(entries, entries[serviceImplementationIndex]);
        return tabs;
      }
      return tabs; 
  };
}