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 toasts are optional: enable Notyf (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.

From 1.1.3, 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). From 1.1.3 the component object is not passed in $scriptProperties: get it via getService. 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.