AjaxForm в модальном Ajax окне

Приветствую!
Мой «101» вопрос про ajaxform )
Задача: выводить форму в модальном окне, контент которого загружается ajax'ом.

Что смог сделать на данном этапе благодаря документации и инструкциям с этого ресурса:

1. Если форма просто в теле документа, то работает всё ок. Окно «своё», т.е. не bootstrap

js которые открывает/закрывает окно и работает с формой
var overlay = $('#modal-overlay');
var modalwindow = $('#modal-window');
var modalclose = $('#modal-window-close, #modal-overlay');
var modalform = $('form#modalform');

$(document).ready(function() { 
	
	$('#callbutton').click( function(event){ 

	overlay.fadeIn(200, 
	 	function(){ 
			modalwindow 
				.css('display', 'block') 
				.animate({opacity: 1}, 200); 
	});
	});

	
	modalclose.click( function(){ 
		modalwindow
			.animate({opacity: 0}, 200,  
				function(){ 
					modalwindow.css('display', 'none'); 
					overlay.fadeOut(200); 
					$("#modal-success-msg").remove();
				}
			);
		modalform.find('.error').html('');
        modalform.find('.error').removeClass('error');
        modalform[0].reset();
	});
});

$(document).on('af_complete', function(event, response) {
    if (response.success) {
            var msgPaste = $( '<div id="modal-success-msg"><span>' + response.message + '</span></div>' );
            msgPaste.appendTo('div.modal-window-wrap');
    }
});

var AjaxForm = {

    initialize: function (afConfig) {
        if (!jQuery().ajaxForm) {
            document.write('<script src="' + afConfig['assetsUrl'] + 'js/lib/jquery.form.min.js"><\/script>');
        }
        

        $(document).off('submit', afConfig['formSelector']).on('submit', afConfig['formSelector'], function (e) {
            $(this).ajaxSubmit({
                dataType: 'json',
                data: {pageId: afConfig['pageId']},
                url: afConfig['actionUrl'],
                beforeSerialize: function (form) {
                    form.find(':submit').each(function () {
                        if (!form.find('input[type="hidden"][name="' + $(this).attr('name') + '"]').length) {
                            $(form).append(
                                $('<input type="hidden">').attr({
                                    name: $(this).attr('name'),
                                    value: $(this).attr('value')
                                })
                            );
                        }
                    })
                },
                beforeSubmit: function (fields, form) {
                    //noinspection JSUnresolvedVariable
                    if (typeof(afValidated) != 'undefined' && afValidated == false) {
                        return false;
                    }
                    form.find('.error').html('');
                    form.find('.error').removeClass('error');
                    form.find('input,textarea,select,button').attr('disabled', true);
                    return true;
                },
                success: function (response, status, xhr, form) {
                    form.find('input,textarea,select,button').attr('disabled', false);
                    response.form = form;
                    $(document).trigger('af_complete', response);
                    if (!response.success) {
                        AjaxForm.Message.error(response.message);
                        if (response.data) {
                            var key, value, focused;
                            for (key in response.data) {
                                if (response.data.hasOwnProperty(key)) {
                                    if (!focused) {
                                        form.find('[name="' + key + '"]').focus();
                                        focused = true;
                                    }
                                    value = response.data[key];
                                    form.find('.error_' + key).html(value).addClass('error');
                                    form.find('[name="' + key + '"]').addClass('error');
                                }
                            }
                        }
                    }
                    else {
                        AjaxForm.Message.success(response.message);
                        form.find('.error').removeClass('error');
                        form[0].reset();
                        //noinspection JSUnresolvedVariable
                        if (typeof(grecaptcha) != 'undefined') {
                            //noinspection JSUnresolvedVariable
                            grecaptcha.reset();
                        }
                    }
                }
            });
            e.preventDefault();
            return false;
        });

        $(document).on('keypress change', '.error', function () {
            var key = $(this).attr('name');
            $(this).removeClass('error');
            $('.error_' + key).html('').removeClass('error');
        });

        $(document).on('reset', afConfig['formSelector'], function () {
            $(this).find('.error').html('');
        });
    }

};


//noinspection JSUnusedGlobalSymbols
AjaxForm.Message = {
    success: function (message, sticky) {
        if (message) {
            
        }
    },
    error: function (message, sticky) {
        if (message) {
            
        }
    },
    info: function (message, sticky) {
        if (message) {
            
        }
    },

};

2. Научился грузить статичные документы в модальное окно через ajax. Спасибо вот этому комменту

js (тестировал только контент подгружать)
$(document).on('click','a#callbutton',function(e){
	e.preventDefault();
	var id = $(this).data('id') || 0;
	$.post("/assets/ajax.php",{action:"getContent",id:id}, function(response) {
	response.success = response.success || false;
	if (response.success) {
		$('.modal-window-wrap','#modal-window').html(response.content);
	}
}, 'json');
});
php
<?php
if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest' || empty($_REQUEST['action'])) {exit();}

$action = $_REQUEST['action'];

define('MODX_API_MODE', true);
require_once dirname(dirname(__FILE__)).'/index.php';

$modx->getService('error','error.modError');
$modx->getRequest();
$modx->setLogLevel(modX::LOG_LEVEL_ERROR);
$modx->setLogTarget('FILE');
$modx->error->message = null;

$output = '';
switch ($action) {
    case 'getContent':
        $id = isset($_POST['id']) ? (int) $_POST['id'] : 0;
        if (empty($id)) {
            exit();
        };

        $object = $modx->getObject('modResource',$id);
	$output = array();
        $output['content'] = $object->get('content');
	$output['pagetitle'] = $object->get('pagetitle');
	$output['success'] = true;
// И выводить в JSON
exit($modx->toJSON($output));
        $maxIterations= (integer) $modx->getOption('parser_max_iterations', null, 10);
        $modx->getParser()->processElementTags('', $output, false, false, '[[', ']]', array(), $maxIterations);
        $modx->getParser()->processElementTags('', $output, true, true, '[[', ']]', array(), $maxIterations);
}

@session_write_close();
exit($output);
Пробовал объединить, но:
если в тело документа прописать чанк — получаю код вызова чанка, а не его содержимое
если в тело дока прописать вызов форму — результат анологичный первому
если в тело докуменда вставить саму форму — капча не грузится, да и форма не работает

Я так понимаю форма не подключается, подскажите как это можно реализовать, её нужно как-то подключать после подгрузки html каркаса?

P.s. про дополнение quickview знаю, не хочу его ставить, надо решение с минимумом кода, без лишних функций
Скаут
04 июля 2017, 10:24
modx.pro
2 396
0

Комментарии: 7

Володя
04 июля 2017, 17:09
+1
так это… местами поменяй
$maxIterations= (integer) $modx->getOption('parser_max_iterations', null, 10);
$modx->getParser()->processElementTags('', $output, false, false, '[[', ']]', array(), $maxIterations);
$modx->getParser()->processElementTags('', $output, true, true, '[[', ']]', array(), $maxIterations);

exit($modx->toJSON($output));
ато у тебя после exit ничего же не отрабатывает
    Скаут
    04 июля 2017, 19:00
    0
    спасибо, исправил, но как бы ситуация в целом никак не поменялась
    Андрей
    04 июля 2017, 21:03
    0
    AjaxForm при вызове сниппета формирует конфиг и запускается через метод AjaxForm.initialize, его можно увидеть в коде страницы.

    Соответственно, наверное, нужно при загрузке формы в окно перевызвать этот метод.

    Не проверял и не уверен что будет работать.

    JS
    $(document).on('click', 'a#callbutton', function() {
      var id = $(this).data('id');
    
      $.ajax({
        url: '/assets/ajax.php',
        method: 'POST',
        dataType: 'json',
        data: {
          action: 'getContent',
          id: id
        }
      })
      .done(function(response) {
        if (response.success) {
          $('.modal-window-wrap','#modal-window').html(response.data.content);
    
          // Тут надо перевызвать AjaxForm
          AjaxForm.initialize(response.config);
    
        } else {
          AjaxForm.Message.error(response.message);
        }
      });
    
      return false;
    });

    PHP
    <?php
    if ($_SERVER['HTTP_X_REQUESTED_WITH'] != 'XMLHttpRequest' || empty($_REQUEST['action'])) {exit();}
    
    define('MODX_API_MODE', true);
    require_once dirname(dirname(__FILE__)).'/index.php';
    
    $modx->getService('error','error.modError');
    $modx->getRequest();
    $modx->setLogLevel(modX::LOG_LEVEL_ERROR);
    $modx->setLogTarget('FILE');
    $modx->error->message = null;
    
    if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'getContent') {
    
      $result = array(
        'success' => false
      );
    
      $id = $_REQUEST['id'];
    
      if (!$id) {
        $result['message'] = 'Не указан ID ресурса';
    
        return json_encode($result, true);
      }
    
      if (!$modx->loadClass('ajaxform', MODX_CORE_PATH . 'components/ajaxform/model/ajaxform/', false, true)) {
        return false;
      }
    
      $AjaxForm = new AjaxForm($modx, array());
    
      $AjaxFormConfig = array(
        'assetsUrl' => $AjaxForm->config['assetsUrl'],
        'actionUrl' => str_replace('[[+assetsUrl]]', $AjaxForm->config['assetsUrl'], $AjaxForm->config['actionUrl']),
        'closeMessage' => $AjaxForm->config['closeMessage'],
        'formSelector' => "form.{$AjaxForm->config['formSelector']}",
        'pageId' => $id
      );
    
      if ($resourse = $modx->getObject('modResource', $id)) {
          $content = $resourse->get('content');
          
          $maxIterations = (integer) $modx->getOption('parser_max_iterations', null, 10);
          $modx->getParser()->processElementTags('', $content, false, false, '[[', ']]', array(), $maxIterations);
          $modx->getParser()->processElementTags('', $content, true, true, '[[', ']]', array(), $maxIterations);
    
          $result['success'] = true;
          $result['config'] = $AjaxFormConfig;
          $result['data'] = array(
              'pagetitle' => $resourse->get('pagetitle'),
              'content' => $content
          );
    
      } else {
          
          $result['message'] = 'Такого ресурса не существует';
          
      }
    
      return json_encode($result, true);
    
    }
      Скаут
      04 июля 2017, 21:23
      0
      Да, видел, так и думал, проблема именно в том, не знаю как технически сделать.

      Ваш вариант попробовал: контент вообще не подтягивается. Окно остаётся пустым, да и ajaxform не перевызывается.

      Ещё вопрос: как именно вызвать форму в теле документа? чанк указывать или форму из чанка вставлять? или может есть вариант без документа напрямую сниппет ajaxform вызвать в окно?
        Андрей
        05 июля 2017, 09:44
        +1
        В документ можно вставить вызов чанка с формой.

        Самый простой вариант — это сделать скрытое модальное окно с формой прямо на странице, а по клику на кнопку/ссылку показывать окно, без всяких ajax.
          Скаут
          05 июля 2017, 13:55
          0
          У меня сейчас как раз и сделано через «самый простой вариант», но хочется всё на ajax завязать
      Сергей Малышев
      24 ноября 2020, 17:27
      0
      У меня на странице несколько разных форм обратной связи. После работы AjaxForm в коде страницы выводится код всех форм. В результате увеличивается время загрузки страницы. Есть ли решение, которое позволяет через Ajax выводить нужную форму, чтобы, при этом код не рендерился в код страницы при загрузке, а вызывался только тогда, когда нужно?
        Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
        7