From: Coleman Watts Date: Sun, 2 Feb 2014 04:58:44 +0000 (-0800) Subject: CRM-13966 - Add method to Core_Form for contactRef fields X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=47f21f3a269ad6f367bbb69e771717df0a4ea103;p=civicrm-core.git CRM-13966 - Add method to Core_Form for contactRef fields --- diff --git a/CRM/Core/Form.php b/CRM/Core/Form.php index a645499491..c604f97c56 100644 --- a/CRM/Core/Form.php +++ b/CRM/Core/Form.php @@ -105,6 +105,14 @@ class CRM_Core_Form extends HTML_QuickForm_Page { */ public $ajaxResponse = array(); + /** + * Stores info about reference fields for preprocessing + * Public so that hooks can access it + * + * @var array + */ + public $entityReferenceFields = array(); + /** * constants for attributes for various form elements * attempt to standardize on the number of variations that we @@ -208,7 +216,7 @@ class CRM_Core_Form extends HTML_QuickForm_Page { * These are not default values * @param bool is this a required field * - * @return object html element, could be an error object + * @return HTML_QuickForm_Element could be an error object * @access public * */ @@ -399,6 +407,8 @@ class CRM_Core_Form extends HTML_QuickForm_Page { // the user can do both the form and set default values with this hook CRM_Utils_Hook::buildForm(get_class($this), $this); + $this->preprocessReferenceFields(); + $this->addRules(); } @@ -1196,6 +1206,88 @@ class CRM_Core_Form extends HTML_QuickForm_Page { $this->setDefaults(array($name => $defaultCurrency)); } + /** + * Create a single or multiple contact ref field + * @param string $name + * @param string $label + * @param array $props mix of html and widget properties, including: + * - required + * - select - params to give to select2, notably "multiple" + * - api - array of data for the api, keys include "entity", "action", "params", "search", "key", "label" + * @return HTML_QuickForm_Element + */ + function addContactRef($name, $label, $props = array(), $required = FALSE) { + $props['class'] = isset($props['class']) ? $props['class'] . ' crm-select2' : 'crm-select2'; + + $props['select'] = CRM_Utils_Array::value('select', $props, array()) + array( + 'minimumInputLength' => 1, + 'multiple' => !empty($props['multiple']), + 'placeholder' => CRM_Utils_Array::value('placeholder', $props, $required ? ts('- select -') : ts('- none -')), + 'allowClear' => !$required, + // Disabled pending https://github.com/ivaynberg/select2/pull/2092 + //'formatInputTooShort' => ts('Start typing a name or email address...'), + //'formatNoMatches' => ts('No contacts found.'), + ); + + $props['api'] = CRM_Utils_Array::value('api', $props, array()) + array( + 'entity' => 'contact', + 'action' => 'getquick', + 'search' => 'name', + 'label' => 'data', + 'key' => 'id', + ); + + $this->entityReferenceFields[$name] = $props; + $this->formatReferenceFieldAttributes($props); + return $this->add('text', $name, $label, $props, $required); + } + + /** + * @param $props + */ + private function formatReferenceFieldAttributes(&$props) { + $props['data-select-params'] = json_encode($props['select']); + $props['data-api-params'] = json_encode($props['api']); + CRM_Utils_Array::remove($props, 'multiple', 'select', 'api'); + } + + private function preprocessReferenceFields() { + foreach ($this->entityReferenceFields as $name => $props) { + $val = $this->getElementValue($name); + $field = $this->getElement($name); + // Support array values + if (is_array($val)) { + $val = implode(',', $val); + $field->setValue($val); + } + if ($val) { + $data = $labels = array(); + // Support serialized values + if (strpos($val, CRM_Core_DAO::VALUE_SEPARATOR) !== FALSE) { + $val = str_replace(CRM_Core_DAO::VALUE_SEPARATOR, ',', trim($val, CRM_Core_DAO::VALUE_SEPARATOR)); + $field->setValue($val); + } + foreach (explode(',', $val) as $v) { + $result = civicrm_api3($props['api']['entity'], $props['api']['action'], array('sequential' => 1, $props['api']['key'] => $v)); + if (!empty($result['values'])) { + $data[] = array('id' => $v, 'text' => $result['values'][0][$props['api']['label']]); + $labels[] = $result['values'][0][$props['api']['label']]; + } + } + if ($field->isFrozen()) { + $field->removeAttribute('class'); + $field->setValue(implode(', ', $labels)); + } + elseif ($data) { + if (empty($props['select']['multiple'])) { + $data = $data[0]; + } + $field->setAttribute('data-entity-value', json_encode($data)); + } + } + } + } + /** * Convert all date fields within the params to mysql date ready for the * BAO layer. In this case fields are checked against the $_datefields defined for the form diff --git a/js/Common.js b/js/Common.js index 14a2c1d23a..0c0a047c5b 100644 --- a/js/Common.js +++ b/js/Common.js @@ -253,14 +253,14 @@ CRM.validate = CRM.validate || { functions: [] }; -// Set select2 defaults -$.fn.select2.defaults.minimumResultsForSearch = 10; -// https://github.com/ivaynberg/select2/pull/2090 -$.fn.select2.defaults.width = 'resolve'; - (function ($, undefined) { "use strict"; + // Set select2 defaults + $.fn.select2.defaults.minimumResultsForSearch = 10; + // https://github.com/ivaynberg/select2/pull/2090 + $.fn.select2.defaults.width = 'resolve'; + // Initialize widgets $(document).on('crmLoad', function(e) { $('table.row-highlight', e.target) @@ -284,7 +284,28 @@ $.fn.select2.defaults.width = 'resolve'; $(this).nextUntil('option[value^=crm_optgroup]').wrapAll(''); $(this).remove(); }); - var options = $(this).data('select2') || {}; + var options = $(this).data('select-params') || {}; + // Api-based searching + if ($(this).data('api-params')) { + $(this).addClass('crm-ajax-select') + options.query = function(info) { + var api = $(info.element).data('api-params'); + var params = api.params || {}; + params[api.search] = info.term; + CRM.api3(api.entity, api.action, params).done(function(data) { + var results = {context: info.context, results: []}; + if (typeof(data.values) === 'object') { + $.each(data.values, function(k, v) { + results.results.push({id: v[api.key], text: v[api.label]}); + }); + } + info.callback(results); + }); + }; + options.initSelection = function(el, callback) { + callback(el.data('entity-value')); + }; + } $(this).select2(options).removeClass('crm-select2'); }); });