Watchfield in Joomla Form: WT CDEK field dependencies

WT CDEK library - Documentation
Category: Libraries

Watchfield in WT CDEK for Joomla covers field bindings, XML, AJAX and Script Options. This reference explains its purpose, parameters and XML examples for Joomla Form.

Watchfield in WT CDEK 1.4.0 connects an existing Joomla Form field to one or more parent fields. When sources change, it retrieves data and notifies the field renderer. Tariffinfo and Deliverypoints use this mechanism.

Set watchfield on the dependent field. The library does not provide type="watchfield". The PHP helper Webtolk\Cdekapi\Helper\Watchfield prepares configuration; WebAsset wtcdek.watchfield observes sources; each field's renderer displays a card or updates a selector. showon controls visibility; watchfield controls value dependencies and data loading.

One source: tariff and details card

<form addfieldprefix="Webtolk\Cdekapi\Fields">
    <fieldset name="tariffs">
        <field name="tariff_code" type="Tarifflist" label="Tariff" />
        <field name="tariff_info" type="Tariffinfo"
               label="Tariff details" watchfield="tariff_code" />
    </fieldset>
</form>

watchfield="tariff_code" observes the XML field named tariff_code in the current group. The shared handler turns a scalar binding into {"value":"tariff_code"}. Tariffinfo understands the value key; AJAX sends this source as a POST parameter named value.

Several sources: city and postal code

<form addfieldprefix="Webtolk\Cdekapi\Fields">
    <fieldset name="address">
        <field name="city" type="text" label="City" />
        <field name="postal_code" type="text" label="Postal code" />
        <field name="point" type="Deliverypoints" label="CDEK pickup point"
               watchfield='{"city":"city","zip":"postal_code"}' />
    </fieldset>
</form>

Map keys are consumer parameters; map values are XML source field names. Deliverypoints allows city, zip and fias_guid; zip is sent to the server as postal_code. For example, watchfield='{"fias_guid":"settlement_fias"}' watches the settlement_fias field, which must exist in the form. Deliverypoints does not support scalar watchfield.

Use a named JSON object with nonempty string keys and field names. A JSON array such as ["city","zip"] is invalid. Single quotes around the XML attribute let you copy JSON with regular double quotes.

Groups, forms and repeatable rows

An unqualified source name resolves within the current Joomla Form group. address.city references city in fields name="address". For a nested group, use e.g. settings.address.city: the last segment is the field name; preceding segments identify the group. A fieldset name alone does not create a data group.

Supply an XML name, not an HTML ID or jform[params][city]. The helper obtains the full input name from Form, so arbitrary control prefixes work. In the browser, lookup stays within the nearest HTML form.

Native repeatable subforms bind source names to the current row index through data-base-name and data-group. Added target containers are discovered automatically; removed targets release subscriptions and abort requests. After custom markup insertion, call Joomla.Watchfield.scan() or dispatch Joomla's joomla:updated event.

Update sequence

  1. PHP resolves source fields through Form::getField() and adds JSON attributes data-watchfield and data-watchfield-options to the target container.
  2. After DOM readiness, the handler binds sources and performs the initial data load.
  3. input and change create a new snapshot. Leading/trailing whitespace is trimmed; internal spaces remain.
  4. A changed snapshot immediately emits watchfield:invalidate. For AJAX, input uses a 250 ms debounce; change updates without that delay. Script Options have no 250 ms debounce.
  5. The previous request is aborted; a late response cannot replace newer data. The same snapshot does not trigger another successful load.
  6. The renderer receives data or an error state and updates its output.

Radio returns the selected value; multiple selects and checkbox groups return arrays. The built-in CDEK examples use scalar address values and tariff codes.

Changing a text input programmatically

Assigning .value does not generate a browser event. Dispatch change after selecting a city in your own autocomplete. Use your source's actual full HTML name:

const city = document.querySelector('input[name="jform[city]"]');

if (city) {
    city.value = 'Саратов';
    city.dispatchEvent(new Event('change', { bubbles: true }));
}

Input covers typing, paste and deletion. For a text field, change normally occurs on blur after editing. When updating several sources programmatically, set their values before dispatching notification events.

Provider attributes

XML attribute Meaning
watchfield-data-source scriptoptions: page data; onpage: alias; ajax: POST request.
watchfield-data-options Literal Joomla Script Options key, e.g. shop.cdek.
watchfield-data-path Dotted path within the returned data; empty means the whole object. Numeric segments address arrays: data.0.options.
watchfield-data-url AJAX endpoint on the same origin: scheme, host and port must match.

Tariffinfo defaults to scriptoptions, the wtcdek.tariffs key and an empty path. Its catalog is prepared server-side through the API/cache. Deliverypoints defaults to ajax, the standard com_ajax URL and data.0.options. Switching source modes without an explicit path resets the path to an empty string. When changing only the URL in the same mode, set the path appropriate to your response format.

Page data: Script Options

Add the catalog in your extension PHP code before the document is output:

use Joomla\CMS\Factory;

Factory::getApplication()->getDocument()->addScriptOptions('shop.cdek', [
    'catalog' => [
        '136' => [
            'tariff_code' => '136',
            'tariff_name' => 'Example tariff',
            'delivery_mode_name' => 'Warehouse to warehouse',
        ],
    ],
]);

Then use this form:

<form addfieldprefix="Webtolk\Cdekapi\Fields">
    <fieldset name="tariffs">
        <field name="tariff_code" type="list" label="Tariff" default="136">
            <option value="">Select a tariff</option>
            <option value="136">Example tariff</option>
        </field>
        <field name="tariff_info" type="Tariffinfo" label="Details"
               watchfield="tariff_code"
               watchfield-data-source="scriptoptions"
               watchfield-data-options="shop.cdek"
               watchfield-data-path="catalog" />
    </fieldset>
</form>

watchfield-data-options="shop.cdek" calls Joomla.getOptions('shop.cdek'). Dots in the options key do not create a path. watchfield-data-path="catalog" selects the catalog property inside that object. Missing Tariffinfo card properties display as empty. Tariffinfo still prepares its standard catalog through the API/cache during rendering, even with a custom client-side source.

Pickup points from page data

use Joomla\CMS\Factory;

Factory::getApplication()->getDocument()->addScriptOptions('shop.delivery', [
    'points' => [
        ['value' => 'SAR141', 'text' => 'Example pickup point'],
    ],
]);
<field name="point" type="Deliverypoints"
       addfieldprefix="Webtolk\Cdekapi\Fields"
       label="CDEK pickup point" city="Саратов"
       watchfield-data-source="scriptoptions"
       watchfield-data-options="shop.delivery"
       watchfield-data-path="points" />

This is demonstration data, not current information about a real point. Deliverypoints expects an array of objects with string value codes and string text labels. Script Options reads the specified array without filtering by city or point type. Apply such filters when preparing your data. The city attribute explicitly selects fixed-address mode, so watchfield is not required here.

A custom AJAX endpoint

<form addfieldprefix="Webtolk\Cdekapi\Fields">
    <fieldset name="tariffs">
        <field name="tariff_code" type="Tarifflist" label="Tariff" />
        <field name="tariff_info" type="Tariffinfo" label="Details"
               watchfield='{"tariff_code":"tariff_code"}'
               watchfield-data-source="ajax"
               watchfield-data-url="index.php?option=com_ajax&amp;group=system&amp;plugin=yourplugin&amp;format=json"
               watchfield-data-path="data.0.catalog" />
    </fieldset>
</form>

yourplugin is your system plugin name: replace it and implement the handler. WT CDEK does not provide an endpoint with this placeholder name. The named map sends tariff_code; a scalar binding would send value.

Example JSON response for data.0.catalog:

{
    "success": true,
    "data": [
        {
            "catalog": {
                "136": {
                    "tariff_code": "136",
                    "tariff_name": "Example tariff",
                    "delivery_mode_name": "Warehouse to warehouse"
                }
            }
        }
    ]
}

The handler uses POST with same-origin credentials, source snapshots, static field parameters and the current token from Joomla.getOptions('csrf.token'). The body is form-urlencoded; arrays use name[]. Your endpoint must validate the CSRF token, access permissions and input values. Do not put a token in XML or source code.

Default Deliverypoints parameters are action=deliverypoints, city, postal_code, fias_guid, type, is_reception and is_handout. For a custom provider, specify its URL and path to the options array; standard com_ajax uses data.0.options. The client sends configured parameters and watched values, not the entire Joomla Form.

An HTTP error, success: false, invalid JSON or a missing data path produces an error state. Default Deliverypoints AJAX is skipped when city, postal_code and fias_guid are all empty; an empty event is emitted instead. Script Options requires no network request.

Events and your own renderer

Event When emitted Additional detail
watchfield:invalidate Source snapshot changed, before loading/debounce. initial: false
watchfield:loading Before AJAX. Not emitted for Script Options. —
watchfield:data Data loaded and path applied. data
watchfield:error Source, transport or data error. message
watchfield:empty All AJAX requiredAny values are empty. —

Events bubble from the target container. Normal state events include values, the source snapshot, and initial. A JSON-attribute parse error before state creation includes only message. Initial means the first load attempt, not necessarily the first successful response. Each field renderer validates its data format.

To build a custom consumer, use the helper with the owning Joomla Form instance in $form:

use Joomla\CMS\Factory;
use Webtolk\Cdekapi\Helper\Watchfield;

// $form is the owning Joomla Form instance.
$document = Factory::getApplication()->getDocument();
$wa = $document->getWebAssetManager();
$wa->getRegistry()->addRegistryFile('media/lib_wtcdek/joomla.assets.json');
$wa->useScript('wtcdek.watchfield');

$document->addScriptOptions('shop.cdek', ['catalog' => []]);
$sources = Watchfield::resolve($form, '{"city":"city"}', 'address');
$attributes = Watchfield::attributes($sources, [
    'source' => 'scriptoptions',
    'options' => 'shop.cdek',
    'path' => 'catalog',
]);
// Render $attributes on your .my-cdek-field container.

Render $attributes on your .my-cdek-field container. Register its renderer as a WebAsset depending on wtcdek.watchfield, so event listeners exist before initial loading:

document.addEventListener('watchfield:data', (event) => {
    if (!event.target.matches('.my-cdek-field')) return;

    const { values, data, initial } = event.detail;
    // Render data for this container; values contains the source snapshot.
});

Version 1.4.0 boundaries

  • scan() discovers new containers and rebinds source nodes. It does not reread changed data attributes on an existing registered container and is not an unconditional refresh. Replace the target container to apply different configuration.
  • Changing Script Options with unchanged source values does not guarantee rendering: snapshots are deduplicated. Provide your own refresh/new container for dynamic datasets.
  • A scan after an error can retry the same address. In 1.4.0 that retry may clear the saved pickup point; automatic selection preservation on retry is not guaranteed.
  • Deliverypoints emits wtcdek:options-updated after programmatically replacing options. Watchfield listens to input/change, so a longer dependency chain through an automatically cleared point needs separate integration. Notify downstream consumers with change when the value actually changes, and avoid cycles.
  • Old layout overrides using data-watch-field/data-tariffs must adopt the current standard layout contract. Existing Tariffinfo XML watchfield and the tariff_field alias remain supported.

Joomla Form Fields

Overview and getting started

WT CDEK 1.4.0 source code on GitHub

WebTolk Joomla Extensions

113 Extensions
12 Categories
587 Versions released
920737 Downloads