Skip to content
  1. Extras
  2. SendIt
  3. Development

Development

Replace miniShop2 notifications

js
document.addEventListener('si:init', (e) => {
    if(typeof miniShop2 !== 'undefined'){
        miniShop2.Message = SendIt.Notify;
    }
});

Send request to custom connector

js
document.addEventListener('si:init', (e) => {
    document.addEventListener('submit', (e) => {
        const target = e.target.closest('.js-my-form');
        if(!target) return;
        const params = new FormData(target);
        const url = 'assets/action.php';
        const headers = {};
        SendIt?.setComponentCookie('sitrusted', '1');
        // v2 (deprecated): SendIt.Sending.send(target, url, headers, params);
        SendIt.Sending.fetch(target, url, headers, params);
    })
});

Внимание

When sending to custom connector, protect the server from XSS and bots.

Send request to standard connector

js
document.addEventListener('si:init', (e) => {
    document.addEventListener('submit', (e) => {
        const target = e.target.closest('.js-my-form');
        if(!target) return;
        const preset = target.dataset[SendIt.Sending.config.presetKey];
        // v2 (deprecated): SendIt.Sending.prepareSendParams(target, preset);
        SendIt.Sending.sendRequest(target, preset);
    })

});

Подсказка

The preset key is expected in the data-si-preset attribute.

Send request WITHOUT form to standard connector

js
document.addEventListener('si:init', (e) => {
    SendIt?.setComponentCookie('sitrusted', '1');
    // v2 (deprecated): SendIt?.Sending?.prepareSendParams(document, 'custom');
    SendIt?.Sending?.sendRequest(document, 'custom');
})

Подсказка

custom is the preset key you added to the preset file.

To limit bot activity, when you receive the response (if sending on page load), set sitrusted to 0:

js
document.addEventListener('si:send:after', (e) => {
    const {action, target, result, headers, Sending} = e.detail;

    if(result.somedata){
        SendIt?.setComponentCookie('sitrusted', '0');
    }
})

Disabling antispam for individual forms

As of 3.1.0, antispam (PoW, behavior signature) is configured per preset. If you do not need it for programmatic requests or search forms, simply omit usePoW and useBehaviorSign in the preset:

php
'search' => [
    'hooks' => '',
    'snippet' => 'searchSnippet',
    // usePoW and useBehaviorSign not set — protection disabled
],

If the preset extends another with antispam enabled, you can disable it explicitly:

php
'fast_form' => [
    'extends' => 'default',
    'usePoW' => 0, 
    'useBehaviorSign' => 0, 
    'validate' => 'name:required',
],

You can also control the protection map via the senditOnGetWebConfig event.

Custom snippet for data processing

Подсказка

In your snippet, preset parameters are available as variables; form data from $_POST, files from $_FILES.

php
if($flag){
    return $SendIt->success($successMessage, ['somedata' => 1234]);
}else{
    return $SendIt->error($validationErrorMessage, ['errors' => ['fieldName' => 'Error text here']]);
}

Подсказка

You can delegate field validation to FormIt by adding the validate parameter to the preset.

Changing file validation parameters from JavaScript

In the example below, the maximum allowed number of files for the upload_design preset is changed based on the selected parent and size:

js
document.addEventListener('si:send:before', (e) => {
    const {fetchOptions, headers} = e.detail;
    if (typeof fetchOptions.body.get === 'function') {
        switch (headers['X-SIPRESET']) {
            case 'upload_design':
                const parent = document.querySelector('[name="parent"]:checked');
                let count = 0;
                if (parent) {
                    const sizeSelect = document.querySelector(parent.dataset.sizeTarget);
                    count = sizeSelect.options[sizeSelect.selectedIndex].value;
                }
                fetchOptions.body.set('params', JSON.stringify({maxCount: count}));
            break;
        }
    }
})

Create form management interface in admin

  1. Install Migx.
  2. Create validators configuration.
    Import this
    json
    {
    "formtabs":[{"MIGX_id":405,"caption":"","print_before_tabs":"0","fields":[{"MIGX_id":2297,"field":"name","caption":"Name","inputOptionValues":"Required if==requiredIf||Password length==checkPassLength||Password confirm==passwordConfirm||User not exists==userNotExists||Blank check==blank||Required==required||Valid email==email||Min length==minLength||Max length==maxLength||Min value==minValue||Max value==maxValue||Contains string==contains||Strip string==strip||Strip HTML tags==stripTags||Allow tags==allowTags||Number check==isNumber||Allow special chars==allowSpecialChars||Date check==isDate||Regexp check==regexp","pos":1},{"MIGX_id":2298,"field":"params","caption":"Parameters","pos":2},{"MIGX_id":2311,"field":"error_text","caption":"Error text","pos":3}],"pos":1}],"columns":[{"header":"Name","dataIndex":"name"},{"header":"Parameters","dataIndex":"params"}]}
  3. Create formfield configuration.
    Import this
    json
    {"formtabs":[{"MIGX_id":406,"fields":[{"field":"name","caption":"Name","pos":1},{"field":"placeholder","caption":"Placeholder","pos":2},{"field":"type","caption":"Type","inputOptionValues":"Text==text||Phone==tel||Email==email||Password==password||Number==number||Checkbox==checkbox||Radio==radio||Hidden==hidden||File==file||Date==date||Date and time==datetime-local||Time==time||Range==range||Color==color||Textarea==textarea||Select==select","pos":3},{"field":"values","caption":"Possible values","description":"separator |","pos":4},{"field":"label","caption":"Label","pos":5},{"field":"step","caption":"Step","pos":6},{"field":"chunk","caption":"Chunk","pos":7},{"field":"atributes","caption":"Other attributes","pos":8},{"field":"validators","caption":"Validators","configs":"validators","pos":9}],"pos":1}],"columns":[{"header":"Name","dataIndex":"name"},{"header":"Label","dataIndex":"label"}]}
  4. Create list_double configuration.
    Import this
    json
    {"formtabs":[{"fields":[{"field":"title","caption":"Title","pos":1},{"field":"content","caption":"Content","pos":2}],"pos":1}],"columns":[{"header":"Title","dataIndex":"title"}]}
  5. Create si_forms configuration.
    Import this
    json
    {"formtabs":[{"caption":"Settings","fields":[{"field":"fid","caption":"Form ID","description":"data-si-form attribute value","pos":1},{"field":"formName","caption":"Form name","pos":2},{"field":"chunk","caption":"Chunk","pos":3}],"pos":1},{"caption":"Parameters","fields":[{"field":"params","caption":"Params list","description":"these override preset params","configs":"list_double","pos":1},{"field":"preset","caption":"Preset","description":"from file","inputOptionValues":"Not selected||login_form||register_form||reset_form||logout_form||callback_form","pos":2}],"pos":2},{"caption":"Fields","fields":[{"field":"fields","caption":"Fields list","configs":"formfield","pos":1}],"pos":3}],"columns":[{"header":"Form name","dataIndex":"formName"}]}
  6. Create a TV of type migx named si_form and attach it to a template.
  7. Create a plugin on OnGetFormParams that loads the form parameters and returns them as an array.
    Plugin example
    php
    switch($modx->event->name){
        case 'OnGetFormParams':
            // MODX 2: $modx->getObject('modResource', 10)
            $resource = $modx->getObject(\MODX\Revolution\modResource::class, 10);
            $forms = json_decode($resource->getTVValue('si_forms'), true);
            $params = [];
            foreach($forms as $form){
                if($form['fid'] === $formName){
                    $paramsRaw = json_decode($form['params'], true);
                    break;
                }
    
            }
            if($paramsRaw){
                foreach($paramsRaw as $p){
                    $params[$p['title']] = $p['content'];
                }
            }
            $modx->event->returnedValues = $params;
            break;
    }