Modx Evo eForm

В инете есть куча статей как использовать этот чудный сниппет. Не смотря на его относительную простоту, мне пришлось довольно много с ним повозиться. Не все было очевидно. Некоторые вещи реально ставили в тупик. Поэтому опишу только тонкости.

  • По сравнению с FormIt(MODX Revo) не очень удобно сделаны обратки(функции обратного вызова). Это две функции вызываемые при загрузке формы и после успешной валидации. Если в Formit можно просто назначить путь до скрипта или сниппет, то тут до вызова eForm надо запустить сниппет и там описать эти функции. Кроме это эти функции в eForm запускаются после валидации до отправки письма и после. Но если запретить отправку(&noemail=1), то функции все равно запустятся. Первую обычно используют для плейсхолдеров, которые стоят в шаблоне письма. А второй, в частности, можно назначить &eFormOnMailSent=`sendOrderToManager`, т.е. после оформления заказа ShopKeeper будет вызвана запись в базу корзины. В этой корзине некоторые функции написаны специально под eForm.
  • Не нашел я плейхолдеров валидации конкретных полей. В FormIt как-то круче это.
  • Не просто заменить отправку почты на свою. Можно через обратку после валидации, но дальше придется самому парсить шаблон отправки и прочее. Т.к. в этом случае отключается встроенная почта. Ну, в принципе, это не страшно.
  • Все шаблоны (самой формы, "спасибо", письма) назначаются как чанки, сниппеты или страницы. Что мне неудобно. Тот же FormIt позволяет загрузить из файла.

Если использовать как положено, то все довольно просто, но выглядит не очень. Нужно чтобы избежать гемороя, после валидации - перенаправить на другую страницу, в там "Ваш заказ принят. Спасибо ....". Но при возврате на предыдущую страницу, в частости в Fierfox, получите кучу гемороя. В виде повторной отправке формы и прочее.С этим, конечно, можно героически бороться и победить. Я тоже так делал, но устав от всего этого сейчас все это делаю через ajax.

Вот реализация модали (bootstrap). Используется jQuery и bootstrap.

  1. Контейнер для модали. Тут и сам контейнер и JS, обеспеспечивающий всю функциональность:
    <div id="bs-oneClick-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="oneClickModal" aria-hidden="true">
      <div class="modal-dialog modal-lg_">
          <div class="modal-content">
            <div     class="modal-header">
              <button type="button" class="close" data-dismiss="modal" aria-hidden="true">X</button>
              <h3 class="modal-title" id="mySmallModalLabel">Покупка в 1 клик</h3>
            </div>
            <div class="modal-body">
                    <div class="well">
           
                     
                    </div>

                        <div id="myModal_form">
    [!inc_out? &outFile=`/assets/....../modalOneClik/modalOneClikFuncs.php`!]        
                       
    [!eForm?
     &formid=`Form1click`
     &tpl=`cppv1clickEformTpl`
     &report=`cppv1clickEformRep`
     &thankyou=`cppv1clickEformThank`
     &subject=`Новый заказ в 1 клик (mySite.ru)`
     &to=`myEmail@yandex.ru` 
     &vericode=`0` 
     &noemail=`1`
     &eFormOnBeforeMailSent=`oneclick_BeforeMailSent`
     &eFormOnMailSent=`oneclick_OnMailSent`
     &protectSubmit=`0` 
    !]

                        </div>


            </div>
            <div class="modal-footer">

           
             </div>
          </div>

      </div>
    </div>

    <script type="text/javascript">
      CFG_1_CLICK={};   
      $('#bs-oneClick-modal').on('show.bs.modal', function (e) {
          //console.log(e);
          var domEl=e.relatedTarget;     
          var $shkItem=$(domEl).parents(".shk-item").eq(0);    
          var name=$shkItem.find("[name=shk-name]").val();
          var price=$shkItem.find(".price .text-primary").html(); 
          $(this).find(".well").html("<h4>"+name+"</h4>&nbsp;&nbsp;&nbsp;<span class='fs22 fb text-primary pull-right'>"+price+"</span>");
          CFG_1_CLICK.idTovar=$shkItem.find("[name=shk-id]").val();    
      });
     
      $(function(){
            $(document).on("submit","#Form1click",function(e){
                e.preventDefault();
                var m_method=$(this).attr('method');
                var m_action=$(this).attr('action');
                var m_data=$(this).serialize();
                var fill_="<h3>Ваш заказ отправлен. Ожидание ответа сервера ... </h3>";
                $("#myModal_form").html(fill_);
                $("#bs-oneClick-modal").find(".well").remove();
               
                $.ajax({
                    type: m_method,
                    url: m_action,
                    data: m_data,
                    resetForm: 'true',
                    success: function(result){
                        var data = $(result).find("#myModal_form").html();
                        $("#myModal_form").html(data);
                    }
                });
            });
        });
    </script>
  2. Функции обратного вызова.
        
                ======  modalOneClikFuncs.php  =========
    <?php
        function <b>oneclick_BeforeMailSent(&$fields)</b>
            {
                global $modx;
                $id = $fields['prod_id'];
                if (!is_numeric($id)) return;
                $url = $modx->makeUrl($id, '', '', 'full');
                $pagetitle = $modx->db->getValue('Select `pagetitle` from '.$modx->getFullTableName('site_content').' where `id`='.$id);   
                $price = $modx->db->getValue('Select `value` from '.$modx->getFullTableName('site_tmplvar_contentvalues').' where `contentid`='.$id.' and `tmplvarid`=4');

    $fields['orderData'] = '<p><a href="'.$url.'" target="_blank">'.$pagetitle.'</a> - '.$price.' руб.</p>';

            }
    //===========================================================================
            function <b>oneclick_OnMailSent(&$fields)</b>
            {
          global $modx;
                if ($modx->db->getRecordCount($modx->db->query("show tables from ".$modx->db->config['dbase']." like '".$modx->db->config['table_prefix']."manager_shopkeeper'"))==0) return;
                $id = $fields['prod_id'];
                if (!is_numeric($id)) return;
               
                $userLoggedIn = $modx->userLoggedIn();
                $userId = $userLoggedIn!==false ? $userLoggedIn['id'] : 0;
              $short_txt =$fields['name'].' ,'.$fields['phone'].' ,'.$fields['comment'];
         
                $price = $modx->db->getValue('Select `value` from `modx_site_tmplvar_contentvalues` where `contentid`='.$id.' and `tmplvarid`=4');
                $arr = array(array('0'=>$id,'2'=>$price,'1'=>1,'catalog'=>0));
               
              $userLoggedIn = $modx->userLoggedIn();
         $userId = $userLoggedIn!==false ? $userLoggedIn['id'] : 0;
               
                $ins_fields = array(
                'short_txt' => $short_txt,
                'content' => $modx->db->escape(serialize($arr)),
                'allowed' => 'all',
                'addit' => '',
                'price' => $price,
                'currency' => 'руб.',
                'date' => date("Y-m-d H:i:s"),
                'note' => 'Заказ в 1 клик.',
                'email' => $fields['email'],
                'phone' => $fields['phone'],
                'payment' => '',
                'tracking_num' => '',
                'status' => 1,
                'userid' => $userId
                );
                $order_id = $modx->db->insert($ins_fields, $modx->getFullTableName('manager_shopkeeper'));   
                $modx->invokeEvent('OnSHKsaveOrder', array('id' => $order_id,'purchases' => serialize($arr)));
                $modx->invokeEvent('OnSHKChangeStatus',array('order_id'=>$order_id,'status'=>1));
      global $report;
      $tpl=file_get_contents($_SERVER['DOCUMENT_ROOT'].'/assets/......../modalOneClik/modalOneClikReport.tpl');  
      $modx->placeholders=$fields;
      $body=$modx->parseDocumentSource($tpl);
                         
         
             include_once($_SERVER['DOCUMENT_ROOT']."/assets/...../phpMailCpp.php");
      $arrTo=array();
      $arrTo['Subject']="Новый заказ в интернет-магазине mySite.ru";
      $arrTo['Body']=$body;
      $arrTo['Email']=array();
      $arrTo['Email'][]="myEmail@mail.ru";
      $arrTo['Email'][]="myEmail@yandex.ru";

      $res=SendMailCpp($arrTo);
       
         
               
            }
    ?>





  3. Чанк "cppv1clickEformTpl"(Главная форма. Значение параметра "tpl")
        
    <div class="text-danger">[+validationmessage+]</div>
    <form method="post" action="[~[*id*]~]" id="Form1click" class="form-horizontal">
        <input type="text" name="prod_id" value="[*id*]" id="prod_id" style="display:none;" class="mrgT10">   
        <input type="hidden" name="formid" value="Form1click">
        <input type="text" name="name" value="" required="required" placeholder="Ваше имя" class="form-control mrgT10">
        <input type="tel" name="phone" value="" required="required" placeholder="номер телефона" class="form-control mrgT10"eform="Номер телефона:string:1: отклонен сервером как невалидный, пожалуйста наберите снова:#REGEX /^\+?[0-9-()]{7,12}+/i">
        <textarea name="comment" id="comment" class="form-control mrgT10" placeholder="Комментарий(не обязательно)"></textarea>   
        <div style="text-align:center; margin-top:20px;">
            <input type="submit" class="button btn-bg btn btn-success buttblue" value="Завершить покупку" >
        </div>
    </form>
  4. Чанк "cppv1clickEformThank"("Спасибо за заказ .....". Появляется вместо формы после успешной валидации. Значение параметра "thankyou")
        
    <h3>Спасибо, ваш заказ принят!</h3>
    <p>
      Мы свяжемся с вами в течение 20 минут.
    </p>  
    <p>
     <b>Состав заказа:</b>

    [+orderData+]

    <br /><br />

    <b>Данные покупателя:</b><br />

    <table cellpadding="3">
    <tr><td>Ф.И.О.:</td><td>[+name+]</td></tr>
    <tr><td>Телефон:</td><td>[+phone+]</td></tr>
    <tr><td>Комментарий:</td><td>[+comment+]</td></tr>
    </table>
     
     
    </p>  

    <p>
                  <span>*</span><small> Для повторной покупки данного товара - обновите страницу.</small>            
    </p>
  5. Чанк "cppv1clickEformRep"(Шаблон письма, отправляемого менеджеру. Значение параметра "report")
        
    <p>В интернет-магазине сделан заказ.</p>
    <b>Состав заказа:</b>

    [+orderData+]

    <br /><br />

    <b>Данные покупателя:</b><br />

    <table cellpadding="3">
    <tr><td>Ф.И.О.:</td><td>[+name+]</td></tr>
    <tr><td>Телефон:</td><td>[+phone+]</td></tr>
    <tr><td>Комментарий:</td><td>[+comment+]</td></tr>

    </table>

При такой организации нет как такового возврата на страницу запроса. Поэтому и нет повторной отправки данных. Но есть и недостатки. Так на ajax запрос мы получаем целиком страницу. Приходится вырезать только "тушку" модали и подменять в активном окне той же модали. Наверняка можно как-то это решить. Но поскольку в данном случае включена пагинация. То это не критично. Короче есть над чем еще подумать.

Но несмотря на недостатки по сравнению с FormIt, есть продвинутый функционал. Так можно запретить повторную отправку формы. Правда мне пришлось как-то с этим бороться. Не давал заказать товар еще раз). Можно даже указать время запрета. Вообще количество параметров у eForm больше.


Комментарии 0






Разрешённые теги: <b><i><br>Добавить новый комментарий: