Отправка формы без перезагрузки страницы

InstantCMS 2.X

Отправка формы через ajax

#1 21 января 2020 в 21:02
Такую отправку я сделал. Получил работающий вариант, но возникли вопросы.
Для примера приведу упрощенный код. Задача — разделить одно число на другое, ответ получить на той же странице.
Контроллер называется division.
  1.  
  2. <?php
  3.  
  4. class division extends cmsFrontend {
  5. public function actionIndex() {
  6. $form = $this->getForm("division");
  7. $errors = false;
  8. $numbers = [];
  9. $template = cmsTemplate::getInstance();
  10. $template->render("index", [
  11. "form" => $form,
  12. "errors" => $errors,
  13. "numbers" => $numbers
  14. ]);
  15.  
  16. }
  17. public function actionCalc() {
  18. if ($this->request->isAjax() === false) {
  19. }
  20. $post = (object)$_POST;
  21. if (is_numeric($post->source) && is_numeric($post->divider) && $post->divider != 0) {
  22. $reply["result"] = (float)$post->source / (float)$post->divider;
  23. $reply["msg"] = "Расчет выполнен.";
  24. } else {
  25. $reply["result"] = "-";
  26. $reply["msg"] = "Данные некорректны. Расчет не выполнен.";
  27. }
  28. $s = json_encode($reply);
  29. header("Content-type: application/json");
  30. echo $s;
  31. }
  32. }
  33.  
  1.  
  2. <?php
  3. class formDivisionDivision extends cmsForm {
  4.  
  5. public function init() {
  6.  
  7. return [
  8. [
  9. "type" => "fieldset",
  10. "childs" => [
  11. new fieldNumber("source", [
  12. "title" => "Исходное число",
  13. "rules" => [
  14. ["required"]
  15. ]
  16. ]),
  17. new fieldNumber("divider", [
  18. "title" => "Делитель",
  19. "rules" => [
  20. ["required"]
  21. ]
  22. ])
  23. ]
  24. ]
  25. ];
  26. }
  27.  
  28. }
  29.  
  1.  
  2. <?php
  3. $d = "Деление";
  4. $this->setPageTitle($d);
  5. $this->addBreadcrumb($d);
  6. ?>
  7. <h1><?php echo $d; ?></h1>
  8. <?php
  9. $this->renderForm($form, $numbers, [
  10. //"action" => "",
  11. //"method" => "post",
  12. "submit" => ["title" => "Рассчитать", "id" => "calc"]
  13. ], $errors);
  14.  
  15. ?>
  16.  
  17. <div id="result"></div>
  18. <div id="msg"></div>
  19.  
  20. <script>
  21.  
  22. $('#calc').on('click',function(e) {
  23.  
  24. var source = $('#source').val();
  25. var divider = $('#divider').val();
  26.  
  27. $.ajax({
  28. url: 'calc',
  29. data: {
  30. 'source' : source,
  31. 'divider' : divider},
  32. type: 'post',
  33. success: function(response){
  34. $('#result').html(response.result);
  35. $('#msg').html(response.msg);
  36. }
  37. });
  38.  
  39. e.preventDefault();
  40. });
  41. </script>
  42.  
Вопросы:
1. Как в шаблоне получить id формы? Чтобы не ковырять зачения так: var source = $('#source').val();
2. Почему в JS адрес обработчика формы задаётся фактически экшеном url: 'calc' ?
3. В моём варианте не работает атрибут required в input, что досадно.
Понимаю, что пошел своим путём и можно всё сделать "классически", но как это сделать пока не знаю.
#2 21 января 2020 в 21:19
@IamB,
Не понял зачем отправлять калькуляцию в php, если яваскрипт сам хорошо делит и умножает.
#3 21 января 2020 в 21:44
Ris, это упрощённый пример. Вам точно нужно разобраться в простыне на 200 строк? Или только суть?
У меня нет намерения грузить кого-то лишними задачами.
#4 21 января 2020 в 21:52

только суть

@IamB
Я понимаю, что какие-либо действия без перезагрузки — это аякс.
Также понимаю, что отправка запросов js-php несколько раз туда-сюда в одной валидации формы не есть хорошо.
Но почему не отправить из php в браузер столько данных, сколько возможно и не работать с этими данными уже в js?
#5 21 января 2020 в 22:17
Ris, а можно я сам буду решать как мне работать с данными в каждой конкретной ситуации?
Но в случае с недокалькулятором, то на боевом сайте его, конечно, стоит решить на JS.
#6 21 января 2020 в 22:32

1. Как в шаблоне получить id формы? Чтобы не ковырять зачения так: var source = $('#source').val();

@IamB
а причём id формы если в примере
  1. $('#source').val();
получения значения поля по id ?
в icms2 id формы динамический
  1. md5(microtime(true))
если не передан атрибут
  1. $attributes['form_id']
а так как вариант получить объект формы при действии для вложенного через
  1. var form = $(this).closest("form");

2. Почему в JS адрес обработчика формы задаётся фактически экшеном url: 'calc' ?

@IamB
наверное потому что action у формы такой? а в ajax url в js перехватчике не определён? или я не понял ситуацию))

3. В моём варианте не работает атрибут required в input, что досадно.

@IamB
возможно ваша js функция вызывается через click а не submit и если же так, то в коде не присутствует цикла проверки полей с учётом required)
#7 21 января 2020 в 22:36

Ris, а можно я сам буду решать как мне работать с данными в каждой конкретной ситуации?

@IamB
Нельзя, конечно же, но что с вами поделать/? smile
Попробуйте посмотреть структуру формы, и найти там id.
$structure = $form->getStructure();
#8 21 января 2020 в 22:44

а причём id формы если в примере получения значения поля по id ?

ideasdigger
Чтобы получить значения полей формы так:
  1. data: $(#id_form).serialize(),
#9 21 января 2020 в 22:52

Чтобы получить значения полей формы так:

@IamB
так я выше в ответе всё рассказал))
1 из вариантов модернизировать ваш
  1. templates/default/controllers/division/index.tpl.php
а именно участок
  1.  
  2. <?php
  3. $this->renderForm($form, $numbers, [
  4. //"action" => "",
  5. //"method" => "post",
  6. "submit" => ["title" => "Рассчитать", "id" => "calc"]
  7. ], $errors);
  8.  
  9. ?>
  10.  
изменить на
  1.  
  2. <?php
  3. $this->renderForm($form, $numbers, [
  4. 'form_id' => "id_form",
  5. //"action" => "",
  6. //"method" => "post",
  7. "submit" => ["title" => "Рассчитать", "id" => "calc"]
  8. ], $errors);
  9.  
  10. ?>
  11.  
и у вашей формы будет id не md5 строка а id_form )
#10 21 января 2020 в 22:59

$structure = $form->getStructure();

Ris
Увы! Здесь id формы не увидел.
#11 21 января 2020 в 23:07
ideasdigger, ваш вариант с id формы сработал. Благодарю!

В результате файл templates/default/controllers/division/index.tpl.php стал таким
  1.  
  2. <?php
  3. $d = "Деление";
  4. $this->setPageTitle($d);
  5. $this->addBreadcrumb($d);
  6. ?>
  7. <h1><?php echo $d; ?></h1>
  8. <?php
  9. $formID = md5(microtime(true));
  10. $this->renderForm($form, $numbers, [
  11. "form_id" => $formID,
  12. "submit" => ["title" => "Рассчитать", "id" => "calc"]
  13. ], $errors);
  14.  
  15. ?>
  16.  
  17. <div id="result"></div>
  18. <div id="msg"></div>
  19.  
  20. <script>
  21.  
  22. $('<?php echo "#".$formID; ?>').submit(function(e) {
  23.  
  24. $.ajax({
  25. url: 'calc',
  26. data: $(this).serialize(),
  27. type: 'post',
  28. success: function(response){
  29. $('#result').html(response.result);
  30. $('#msg').html(response.msg);
  31. }
  32. });
  33.  
  34. e.preventDefault();
  35. });
  36. </script>
  37.  
И атрибут required в input теперь работает.
Вы не можете отвечать в этой теме.
Войдите или зарегистрируйтесь, чтобы писать на форуме.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.