Skip to content
Snippets Groups Projects
Commit 917c5c25 authored by Sean Madsen's avatar Sean Madsen Committed by GitHub
Browse files

Merge pull request #279 from seamuslee001/quickform_reference

Migrate Quickform Reference Documents
parents 69240354 a7231c27
No related branches found
No related tags found
No related merge requests found
# EntityRef Fields
## Introduction
This widget was added in CiviCRM v4.5 and supplants the old autocomplete + hidden field techniques. A flexible form widget for finding/selecting/creating contacts and other entities.
## Features
- Developer friendly, takes 1 line of code, no need for additional scripts or templates.
- Works with any entity that has a (searchable) api.
- Supports formatted descriptions and icons in search results.
- Infinite scrolling of search results.
- Add "create new" buttons for contacts (and potentially other entities). This is implemented as a popup for contacts and inline for tags.
- As of CiviCRM v4.6 supports search filters.
- Request "extra" data from the api to be returned along with search results.
## Usage
An entityRef widget can be created via quickform on the server-side, or
using jQuery on the client-side.
### PHP: From a buildForm function
```php
// With no parameters passed in, will create a single contact select
$this->addEntityRef('field_1', ts('Select Contact'));
// Pass some params to allow creation of contacts, set multiple and make the field required
$this->addEntityRef('field_2', ts('Select More Contacts'), array('create => TRUE', 'multiple' => TRUE), TRUE);
// Set some filters in the api (in this case limit results by contact type)
$this->addEntityRef('field_3', ts('Select Organization'), array(
'api' => array(
'params' => array('contact_type' => 'Organization'),
),
));
// Select events instead of contacts - set minimumInputLength to 0 to display results immediately without waiting for search input
$this->addEntityRef('field_4', ts('Select Event'), array(
'entity' => 'event',
'placeholder' => ts('- Select Event -'),
'select' => array('minimumInputLength' => 0),
));
// Use the 'option_value' entity for most "option" lists, e.g. event types, activity types, gender, individual_prefix, custom field options, etc.
$this->addEntityRef('field_5', ts('Activity Type'), array(
'entity' => 'option_value',
'api' => array(
'params' => array('option_group_id' => 'activity_type'),
),
'select' => array('minimumInputLength' => 0),
));
```
Please see code-level documentation in [CRM_Core_Form](https://github.com/civicrm/civicrm-core/blob/master/CRM/Core/Form.php#L1813) for all available params.
### JS: Add from client-side
```html
<input name="my_field" placeholder="{ts}- select organization -{/ts}" />
<script type="text/javascript">
CRM.$(function($) {
// Note: all params accepted by the php addEntityRef also work here
// For example, select organization with button to add a new one:
$('[name=my_field]').crmEntityRef({
api: {params: {contact_type: 'Organization'}},
create: true
});
});
</script>
```
!!! note
Instead of passing params into the `jQuery.crmEntityRef` function, an alternative is to attach them as html data attributes. This is how they are passed from php forms onto the client-side.
## Getlist API
A special [api getlist](https://github.com/civicrm/civicrm-core/blob/master/api/v3/Generic/Getlist.php) action exists to support this widget. Getlist is a wrapper around the "get" action which smooths out the differences between various entities and supports features of the select2 widget such as infinite scrolling. It accepts the following settings (passed into the entityRef widget as 'api' property):
- `search_field`: name of field your user is searching on when s/he types (default depends on entity)
- `label_field`: name of field to display (defaults same as search field)
- `description_field`: one or more fields to be shown as description in autocomplete results
- `extra`: other fields you would like the api to retrieve for additional client-side logic. Can be accessed as `$('#element').select2('data').extra`
- `params`: array of params to send to the underlying api (use for setting additional filters e.g. contact type)
Getlist accepts other params but they are managed internally by the widget (e.g `page_num`) and do not need to be accessed directly.
There are four steps to building a Getlist
1. Defaults
2. Params
3. Output
4. Postprocess
### Defaults
This step ensures minimal requirements for building a Getlist result. It is primarily concerned with properties consumed in the Output stage.
### Params
This step manipulates the parameters to the API magic get function. The core function ensures the api params include the return fields needed by Output. You should be sure to ensure the same return fields if you override this, or call the core function in your override. This step immediately precedes the API Entity Get.
### Output
This step immediately follows the API Entity Get and allows for manipulation of the result of the Entity get API call.
### Postprocess
Is concerned with flattening API-chained calls and the extra fields into the main API response values array. There is no way to extend this step.
### Customizing the output
Some entities are more complex and require additional pre/post processing of autocomplete results, for example to format the description differently or sort the results by date instead of alphabetically. For this, the following generic functions can be overridden: `_civicrm_api3_generic_getlist_defaults`, `_civicrm_api3_generic_getlist_params` and `_civicrm_api3_generic_getlist_output`. See [contact](https://github.com/civicrm/civicrm-core/blob/4.7.14/api/v3/Contact.php#L1248) and [event](https://github.com/civicrm/civicrm-core/blob/4.7.14/api/v3/Event.php#L237) apis for example implementations.
#### `_civicrm_api3_{$entity}_getlist_defaults($apiParams)`
Unlike `_params` and `_output`, this is not an override of the core function. The return of your function will be fed in as the $apiDefaults (with precedence) to the [core defaults function](https://github.com/civicrm/civicrm-core/blob/4.7.14/api/v3/Generic/Getlist.php#L33). Despite the name, the defaults are only used by Getlist. If you do include a params array in the return, it will persist as defaults to API Entity get, but user supplied values will override them.
The input is not the API request but the params array of the API request. You most likely will implement this hook if you want to ensure settings get passed to a your own custom `_output` implementation, or change core behavior such as page size or set default label or id fields for your custom entity.
#### `_civicrm_api3_{$entity}_getlist_params(&$getlistRequest)`
Override function that can be used to alter API Entity Get parameters. You must call the [core function](https://github.com/civicrm/civicrm-core/blob/4.7.14/api/v3/Generic/Getlist.php#L143) if you do not ensure the needed return-field params in your override.
The parameter is a custom "object"(array) that is the product of the `_defaults()` step. The top level consists of settings used by `_output()` as well as a "params" array which will be passed the API Entity get call. The argument is passed by-reference and your override should not have a return.
#### `_civicrm_api3_{$entity}_getlist_output($result, $request, $entity, $fields)`
Override function that is expected to iterate over the "values" portion of the API result and return a values array that is passed again to `api3_create_success()`.
You will likely want to call the [core function](https://github.com/civicrm/civicrm-core/blob/4.7.14/api/v3/Generic/Getlist.php#L159) from your override.
## Select2
On the client side, this widget is rendered using `jQuery.select2`. See [api documentation for the select2 widget](http://ivaynberg.github.io/select2/).
# QuickForm Reference
## Background
Data-entry forms in CiviCRM use an extended variation of [PEAR](http://pear.php.net/)'s `HTML_QuickForm` system. In QuickForm, a web developer defines a new form by creating a "Form" class which implements certain methods (such as "buildForm") and which calls methods to add new form fields (or "elements"). Reference materials for the main QuickForm system can be found online:
- [HTML_QuickForm Documentation Home](http://pear.php.net/package/HTML_QuickForm/docs)
- [HTML_QuickForm Tutorial](http://www.devarticles.com/c/a/Web-Graphic-Design/Using-HTML-Quickform-for-Form-Processing/)
- [HTML_QuickForm Element List](http://pear.php.net/manual/en/package.html.html-quickform.intro-elements.php)
- [(Old Blog) Summary of Page Processing Tools in CiviCRM](http://civicrm.org/node/96)
- [Koumbit QuickForm Cheatsheet](https://wiki.koumbit.net/CiviCrm/QuickForm)
## The Basics
A typical form in CiviCRM looks like this:
```php
class CRM_Example_Form extends CRM_Core_Form {
/**
* @var string - Note make variables public to allow form hooks access
*/
public $_foo;
/**
* This function is called prior to building and submitting the form
*/
public function preProcess() {
// Perform any setup tasks you may need
// often involves grabbing args from the url and storing them in class variables
$this->_foo = CRM_Utils_Request::retrieve('foo', 'String');
}
/**
* Will be called prior to outputting html (and prior to buildForm hook)
*/
public function buildQuickForm() {
// Add elements to the form
$this->add('text', 'my_text_field', ts('Enter Some Text'));
}
/**
* If your form requires special validation, add one or more callbacks here
*/
public function addRules() {
$this->addFormRule(array('CRM_Example_Form', 'myRules'));
}
/**
* Here's our custom validation callback
*/
public static function myRules($values) {
$errors = array();
if ($values['foo'] != 'abc') {
$errors['foo'] = ts('You entered the wrong text!');
}
return empty($errors) ? TRUE : $errors;
}
/**
* Called after form is successfully submitted
*/
public function postProcess() {
// get the submitted values as an array
$vals = $this->controller->exportValues($this->_name);
// Save to the database
civicrm_api3('foo', 'create', $vals);
}
}
```
!!!note
In CiviCRM Core, sometimes in sub classes e.g. in the Custom Search Sub classes, the function `buildForm` is used instead of `buildQuickForm, However there will be a call in the parent function for `buildQuickFrom` which then includes the subClasses buildForm. This is not standard for new form classes.`
## Form Elements
### Basic Types
These basic elements can be added using `CRM_Core_Form()->add()`
| Type | Notes |
| --- | --- |
| text | |
| textarea | |
| select | give it css class "crm-select2" to add select2 widget |
| advcheckbox | like "checkbox" element but normalizes data in postProcess |
| radio | |
| group | mainly useful to contain radios, see addRadio extended method |
| hidden | does not need to be added to the template |
| advmultiselect | takes up a lot of space - consider using select.crm-select2 |
| submit | |
| password | |
### Extended Types
`CRM_Core_Form` includes methods to add special types or sets of form elements not included in basic quickform. See code-level function documentation for details.
| Method | Used For | Notes |
| --- | --- | --- |
| addButtons | form submit buttons | |
| addRado | set of radio buttons | |
| addYesNo | radio buttons with preset 'Yes' & 'No' options | |
| addCheckbox | set of checkboxes | |
| addDateRange | set of "to" and "from" dates | requires an extra template to be included |
| addSelect | autogenerate a select, fetching title and option list from metadata | uses "select2" widget. also adds an "edit options" button visible to admin users *note: to add a select2 that references an entity, see **addEntityRef** below* |
| addProfileSelector | widget by which users can select, create and edit a profile form | requires extra javascript files added using `CRM_Core_Resources` |
| addSelectOther | select or other option | requires extra javascript in the template |
| addUploadElement | file upload | |
| addCurrency | select currency | |
| addMoney | money field + select currency | |
| addEntityRef | autocomplete select of contacts, tags, events, etc. | [EntityRef documentation](/framework/quickform/entityref) |
### Deprecated Form Elements
| Method | Was Used For | Notes |
| --- | --- | --- |
| ~~addDate~~ | Datepicker Element | Use `$form()->add('datepicker', ...)` instead. |
| ~~addDateTime~~ | Datepicker with time Element | Use `$form()->add('datepicker', ...)` instead. |
| ~~addWysiwyg~~ | Rich text Area | Removed: Use `$form()->add("wysiwyg", ... )` instead. |
| ~~addCountry~~ | Country Select Field | Removed. Use AddSelect instad or addEntityRef |
## Request Lifecycle
![](/img/quickform-lifecycle.png)
CiviCRM provides a more nuanced request lifecycle than traditional `HTML_QuickForm`. This extended request lifecycle allows the original web developer to create the form using a class – and allows third-party developers to modify the form using hooks. The request lifecycle is divided into a few phases, and each phase may have multiple steps. The phases and steps are presented in sequence:
### Build Phase
Generate a set of HTML form fields (`$form->addElement()`, `$form->add()`, etc) and validation rules (`$form->addFormRule()`) to the form. (Note: The "Build" phase runs during the initial GET request and the subsequent POST request.)
| Step | Audience | Comments |
| --- | --- | --- |
| `CRM_Core_Form::preProcess` (override) | Original Developer | In any subclass of `CRM_Core_Form`, the `preProcess()` function can be overridden. |
| `CRM_Core_Form::buildQuickForm` (override) | Original Developer | In any subclass of `CRM_Core_Form`, the `buildQuickForm()` function can be overridden. |
| [hook_civicrm_buildForm](/hooks/hook_civicrm_buildForm.md) | Third-Party Developer | |
| `CRM_Core_Form::addRules` (override) | Original Developer | In any subclass of `CRM_Core_Form`, the `addRules()` function can be overridden.
### Validate Phase
Examine submitted form data to determine validity. (Note: The "Validation" phase runs during the POST request.)
| Step | Audience | Comments |
| --- | --- | --- |
| (Process rules) | Original Developer & Third-Party Developer | Iteratively process any rules that here added during the "build" phase (i.e. call any callbacks registered via `$form()->addFormRule()`). |
| [hook_civicrm_validate()](/hooks/hook_civicrm_validate.md) | Third-Party Developer | (Note: This is similar to `hook_civicrm_validateForm` but older) |
| [hook_civicrm_validateForm()](/hooks/hook_civicrm_validateForm.md) | Third-Party Developer | (Note: This is similar to `hook_civicrm_validate`; added in CiviCRM v4.2) |
### Process Phase
Save the data, execute business logic, etc. (Note: The "Process" phase runs during the POST request – but only if the "Validation" was successful)
| Step | Audience | Comments |
| --- | --- | --- |
| `CRM_Core_Form::postProcess` (override) | Original Developer | In any subclass of `CRM_Core_Form`, the `postProcess()` function can be overridden. |
| [hook_civicrm_postProcess](/hooks/hook_civicrm_postProcess.md) | Third-Party Developer | |
### Render Phase
Generate HTML using Smarty.
!!! note
The "Render" phase does not provide events or hooks to the PHP controller.
# hook_civicrm_validate
## Summary
**(Removed)** This hook is invoked during all CiviCRM form validation. An array of errors
detected is returned. Else we assume validation succeeded.
## Availability
This hook was **removed in v4.7**.
## Definition
```php
hook_civicrm_validate($formName, &$fields, &$files, &$form)
```
## Parameters
* string `$formName` - The name of the form.
* array `&$fields` - the POST parameters as filtered by QF
* array `&$files` - the FILES parameters as sent in by POST
* array `&$form` - the form object
## Returns
* mixed - formRule hooks return a boolean or an array of error messages which display a QF Error
......@@ -56,6 +56,7 @@ This is an overview list of all available hooks, listed by category.
* **[hook_civicrm_idsException](/hooks/hook_civicrm_idsException.md)** - allows you to modify the list of form or page paths where submitted data should not be sent through PHPIDS, the intrusion detection system (IDS).
* **[hook_civicrm_postProcess](/hooks/hook_civicrm_postProcess.md)** - invoked when a CiviCRM form is submitted.
* **[hook_civicrm_preProcess](/hooks/hook_civicrm_preProcess.md)** - can be used to modify the behavior of a form before the `buildQuickForm` call.
* **[<del>hook_civicrm_validate</del>](/hooks/hook_civicrm_validate.md)** - **(Removed)** invoked during all CiviCRM form validation. An array of errors detected is returned. Else we assume validation succeeded.
* **[hook_civicrm_validateForm](/hooks/hook_civicrm_validateForm.md)** - allows you to customize the logic used to validate forms.
## GUI hooks
......
docs/img/quickform-lifecycle.png

59.6 KiB

......@@ -76,6 +76,9 @@ pages:
- Region Reference: framework/region.md
- Upgrade Reference: framework/upgrade.md
- Setting Reference: framework/setting.md
- QuickForm Reference:
- QuickForm: framework/quickform/index.md
- Entity Reference Field: framework/quickform/entityref.md
# Other Reference:
# CiviMail: /reference/civimail.md
# CiviReport: /reference/civireport.md
......@@ -133,6 +136,7 @@ pages:
- hook_civicrm_idsException: hooks/hook_civicrm_idsException.md
- hook_civicrm_postProcess: hooks/hook_civicrm_postProcess.md
- hook_civicrm_preProcess: hooks/hook_civicrm_preProcess.md
- <del>hook_civicrm_validate</del>: hooks/hook_civicrm_validate.md
- hook_civicrm_validateForm: hooks/hook_civicrm_validateForm.md
- GUI hooks:
- hook_civicrm_alterMenu: hooks/hook_civicrm_alterMenu.md
......
......@@ -153,3 +153,5 @@ IDE+Settings+to+Meet+Coding+Standards tools/phpstorm
API+changes api/changes
Ajax+Pages+and+Forms framework/ajax
Coding+Standards standards
QuickForm+Reference framework/quickform
EntityRef+Fields framework/quickform/entityref
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment