Skip to content
  1. Extras
  2. FetchIt
  3. Migration from AjaxForm

Migration from AjaxForm ​

Checklist for replacing AjaxForm with FetchIt: styles, toasts, snippet call, markup, custom handler, and JS events.

Styles ​

FetchIt does not load CSS. Set invalid-field classes in fetchit.frontend.input.invalid.class and, if needed, fetchit.frontend.custom.invalid.class. Keep the styles in your site theme.

Notifications ​

AjaxForm ships jGrowl. In FetchIt notifications are optional: turn on the built-in ones with fetchit.frontend.default.notifier, or plug in your own library.

Examples.

Snippet call ​

Main parameters (form, snippet, actionUrl, clearFieldsOnSuccess) stay the same. The JS path and class name moved to system settings. Parameters frontend_css and formSelector are gone.

modx
[[!FetchIt?
  &form=`chunk name`
  &snippet=`FormIt`
  &actionUrl=`[[+assetsUrl]]action.php`
  &clearFieldsOnSuccess=`1`
  &frontend_js=`` // System setting: fetchit.frontend.js
  &objectName=`` // System setting: fetchit.frontend.js.classname
  &frontend_css=``
  &formSelector=``
]]
fenom
{'!FetchIt' | snippet : [
  'form' => 'chunk name',
  'snippet' => 'FormIt',
  'actionUrl' => '[[+assetsUrl]]action.php',
  'clearFieldsOnSuccess' => true,
  'frontend_js' => '', // System setting: fetchit.frontend.js
  'objectName' => '', // System setting: fetchit.frontend.js.classname
  'frontend_css' => '', 
  'formSelector' => '', 
]}

Form markup ​

Error selectors: use [data-error="name"] instead of .error_name. The ajax_form class is not needed: the snippet adds data-fetchit.

For AJAX add [data-success] and [data-validation-error] (see selectors). With AjaxForm, [[+fi.successMessage]] after a reload was often enough.

AjaxForm chunk → FetchIt:

modx
<form action="[[~[[*id]]]]" method="post" class="ajax_form"> 
<form action="[[~[[*id]]]]" method="post"> 

  <div class="form-group">
    <label class="control-label">Name</label>
    <div class="controls">
      <input type="text" name="name" value="[[+fi.name]]" class="form-control"/>
      <span class="error_name">[[+fi.error.name]]</span> 
      <span data-error="name">[[+fi.error.name]]</span> 
    </div>
  </div>

  <div class="form-group">
    <label class="control-label">Email</label>
    <div class="controls">
      <input type="email" name="email" value="[[+fi.email]]" class="form-control"/>
      <span class="error_email">[[+fi.error.email]]</span> 
      <span data-error="email">[[+fi.error.email]]</span> 
    </div>
  </div>

  <div class="form-group">
    <label class="control-label">Message</label>
    <div class="controls">
      <textarea name="message" class="form-control" rows="5">[[+fi.message]]</textarea>
      <span class="error_message">[[+fi.error.message]]</span> 
      <span data-error="message">[[+fi.error.message]]</span> 
    </div>
  </div>

  <div role="alert" data-success style="display: none;"></div> 
  <div role="alert" data-validation-error style="display: none;"></div> 

  <div class="form-group">
    <div class="controls">
      <button type="reset" class="btn btn-default">Reset</button>
      <button type="submit" class="btn btn-primary">Submit</button>
    </div>
  </div>
</form>
fenom
<form action="{$_modx->resource.id | url}" method="post" class="ajax_form"> 
<form action="{$_modx->resource.id | url}" method="post"> 

  <div class="form-group">
    <label class="control-label">Name</label>
    <div class="controls">
      <input type="text" name="name" value="{$_modx->getPlaceholder('fi.name')}" class="form-control"/>
      <span class="error_name">{$_modx->getPlaceholder('fi.error.name')}</span> 
      <span data-error="name">{$_modx->getPlaceholder('fi.error.name')}</span> 
    </div>
  </div>

  <div class="form-group">
    <label class="control-label">Email</label>
    <div class="controls">
      <input type="email" name="email" value="{$_modx->getPlaceholder('fi.email')}" class="form-control"/>
      <span class="error_email">{$_modx->getPlaceholder('fi.error.email')}</span> 
      <span data-error="email">{$_modx->getPlaceholder('fi.error.email')}</span> 
    </div>
  </div>

  <div class="form-group">
    <label class="control-label">Message</label>
    <div class="controls">
      <textarea name="message" class="form-control" rows="5">{$_modx->getPlaceholder('fi.message')}</textarea>
      <span class="error_message">{$_modx->getPlaceholder('fi.error.message')}</span> 
      <span data-error="message">{$_modx->getPlaceholder('fi.error.message')}</span> 
    </div>
  </div>

  <div role="alert" data-success style="display: none;"></div> 
  <div role="alert" data-validation-error style="display: none;"></div> 

  <div class="form-group">
    <div class="controls">
      <button type="reset" class="btn btn-default">Reset</button>
      <button type="submit" class="btn btn-primary">Submit</button>
    </div>
  </div>
</form>

Custom snippet instead of FormIt ​

AjaxForm expected JSON with key status (0/1). FetchIt expects success (bool). The component object is not passed in $scriptProperties: get it with FetchIt::service($modx). Example: custom snippet.

Client-side validation ​

Before (jQuery + AjaxForm):

js
$(document).on('submit', '.ajax_form', function() {
  // Validation code
  afValidated = false;
});

After:

js
document.addEventListener('fetchit:before', (e) => {
  const { form, fetchit } = e.detail

  // Validation code

  // If validation failed
  fetchit.setError('field_name', 'Error message') // optional
  e.preventDefault()
})

Important!

Client-side validation is not secure and should only be used to improve user experience.

Event af_complete ​

AjaxForm has one event after the server response. Equivalent: fetchit:after. It fires on both success and error. For branching use fetchit:success and fetchit:error.

Before:

js
$(document).on('af_complete', function(event, response) {
  var form = response.form
  if (form.attr('id') == 'my_form_3') {
    form.hide()
  } else {
    console.log(response)
  }
})

After:

js
document.addEventListener('fetchit:after', (e) => {
  const { form, response } = e.detail
  if (form.getAttribute('id') === 'my_form_3') {
    form.style.display = 'none'
  } else {
    console.log(response)
  }
})

Внимание

detail.form is a native HTMLFormElement, not a jQuery object. It has no attr() or hide() methods.