1

Using Drupal 10.1.8 and webform 6.2.2

Done a bit of searching, and the only questions I find similar, are quite old. This one seems the best match: AJAX autocomplete based on other field value

Now, my question:

I have two fields:

Client Company : Entity Lookup / autocomplete on taxonomy term

Client project Manager : Entity Lookup to user via a view entity ref.

enter image description here

So, as noted, I want the Client Project Manager field to pass the value (entity id) that was placed in the 'Client Company' field, so as to allow the view to filter.

I am good with all the hooks etc to apply the filter, what I cannot figure out is how to pass that value. I can do as per the noted linked question, and implement some custom js to deal with the fields, but, is that still really the only way?

I, for example, tried using a token in the dependant field's 'view arguments', which, seems the way to go logically, but, the token is just passed, as is, as a string, not the value.

Am i just maybe formatting the token wrong?

I am fairly new to Drupal.

enter image description here

enter image description here

UPDATE: I did just notice the double :: in the token, and fixed that, but the end result is still the same (got excited there for a moment!)

enter image description here

1 Answer 1

0

As per discussions on Slack, this is not an out of the box feature, and requires custom code.

I did not need to make it complicated, as I only need this in one place, on one form (for now), so I solved it with some javascript and manipulating the autocomplete path of the 2nd element.

This way I keep all the standard webform elements (so no custom elements needed) and use the drupal native autocomplete functionality.

First, I created a new javascript file with my custom code. Not going to explain what the code does, it is pretty straight forward, but, ask if something needs clarification.

(function ($, Drupal, once) {
  Drupal.behaviors.autocompleteHook = {
    attach: function (context) {
      if (!once('companyHook', 'html').length) {
        return;
      }
      $('body').on('autocompleteclose', '#edit-client-company', function (e) {
        setTargetPath(e.target.value);
      });
      // if loaded for an edit.
      setTargetPath($('#edit-client_company').val());
    },
  };

  function setTargetPath(elementValue) {
    $('.js-form-item-client-project-manager').hide();
    if(elementValue) {
      var regex = /\((\d+)\)/;
      var match = elementValue.match(regex);
      if (match && match[1]) {
        $('.js-form-item-client-project-manager').show();
        let url = updateUrlParameter($('#edit-client-project-manager').attr('data-autocomplete-path'), 'target_id', match[1]);
        $('#edit-client-project-manager').attr('data-autocomplete-path', url);
      }
    }
  }

  function updateUrlParameter(url, param, paramVal) {
    var newAdditionalURL = '';
    var tempArray = url.split('?');
    var baseURL = tempArray[0];
    var additionalURL = tempArray[1];
    var temp = '';

    if (additionalURL) {
      var tmpAnchor = additionalURL.split('&');
      var paramExists = false;

      for (var i = 0; i < tmpAnchor.length; i++) {
        if (tmpAnchor[i].split('=')[0] == param) {
          tmpAnchor[i] = param + '=' + paramVal;
          paramExists = true;
        }
        temp += i < (tmpAnchor.length - 1) ? tmpAnchor[i] + '&' : tmpAnchor[i];
      }

      if (!paramExists) {
        temp += '&' + param + '=' + paramVal;
      }
    } else {
      temp = param + '=' + paramVal;
    }

    newAdditionalURL = baseURL + '?' + temp;
    return newAdditionalURL;
  }
})(jQuery, Drupal, once);

I added a custom class 'hidden' to the 2nd element, forgoing with the built in element dependency display rules. I have that in my global theme css already as display: none

enter image description here

Then following bog standard drupal ways, I created the needed entry in [module].libraries.yml

autocompleteCompany:
  js:
    js/ihop-autocomplete-company.js: {}
  dependencies:
    - core/jquery
    - core/once

and then in the form's WebformHandler::alter_form function (Using webform handlers, as apposed to hooks in .module file), I attached that library

public function alterForm(
    array &$form,
    FormStateInterface $form_state,
    WebformSubmissionInterface $webform_submission
  ) {

....

$form['#attached']['library'][] = 'ihop/autocompleteCompany';

....
}

so, upon doing a selection of the first field's autocomplete, my js hook fires (listening to autocompleteclose) which then:

  1. Makes the 2nd element visible / invisible, depending on some factors.
  2. Injects or updates the attribute data-autocomplete-path of the 2nd element. Thsi then now passes an additional param, target_id

The last(ref note below) step here is then to get the value of that param in a view hook (located in the .module file), and use it to set a filter.

case 'list_client_pm_entity_ref':
      $companyId =  $view->getRequest()->query->get('target_id');
      $filters['field_company_target_id']['value'] = [$companyId => $companyId];
      break;

Note: At this point, it works only if you use a different lookup string in the 2nd field. This is due to autocomplete.js caching the results.

So, that is my next step, and there is some details here: How to prevent Autocomplete Caching?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.