Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Результаты формы (https://javascript.ru/forum/misc/78225-rezultaty-formy.html)

_marisha 12.08.2019 09:10

Результаты формы
 
Доброго времени суток!
На сайте при добавлении товара в корзину справа отображается форма для ввода информации с 2 полями с выпадающим списком.
<div class="form-body">
    <div class="place_sections_block">
      <div class="row">
      	<div class="col-md-12">
      	   <div class="form-group animated-labels input-filed">
      		   <label for="POPUP_SERVICE">Раздел</label>
             <div class="input">
                <select name="" class="place_sections form-control">
                  <?foreach ($sections as $section){?>
                    <option value="<?=$section['ID']?>"><?=$section['NAME']?></option>
                  <?}?>
                </select>
            </div>
          </div>
        </div>
      </div>
    </div>
    <?$counter = 0;
    foreach ($sections as $section){?>
      <div class="row place_elements<?=++$counter==1?' active':''?>" id="placeElements<?=$section['ID']?>">
      	<div class="col-md-12">
      	   <div class="form-group animated-labels  input-filed">
      		   <label for="POPUP_SERVICE">Место</label>
             <div class="input">
              <select class="form-control">
                <?foreach ($section['elements'] as $element){?>
                  <option value="<?=$element['ID']?>"><?=$element['NAME']?></option>
                <?}?>
              </select>
            </div>
          </div>
        </div>
      </div>
    <?}?>
  </div>

Далее, при нажатии на кнопку "Выбрать" данная форма закрывается и информация передается в корзину.
<div class="form-footer clearfix">
    <span class="btn btn-default placeChoose">Выбрать</span>
  </div>

$(document).ready(function(){
  $('.place_sections').on('change', function(){
    var val = $(this).val();
    $('.place_elements.active').removeClass('active');
    $('#placeElements' + val).addClass('active');
  });

  $('.placeChoose').on('click', function(){
    var val = $('.place_elements.active select').val(),
        name = $('.place_elements.active select option:selected').html();
    $.ajax({
      method: 'post',
      url: '/ajax/actions.php',
      data: {action: 'setPlace', place_id: val},
      success: function(data){
        var result = JSON.parse(data);
        if (result){
          whenPlaceChoosen(name); //custom.js
        }
      }
    })
  });
});

Вместо 2 полей необходимо сделать обычное поле для заполнения.
Делаю так (т.е. второе поле убираю)
<div class="place_sections_block">
      <div class="row">
      	<div class="col-md-12">
      	   <div class="form-group animated-labels input-filed">
      		   <label for="POPUP_SERVICE">Город</label>
             <div class="input">
             	<input type="" name="" class="place_sections form-control">
            </div>
          </div>
        </div>
      </div>
    </div>

После чего, при нажатии на "Выбрать" форма не закрывается.
Подскажите, пожалуйста, что делаю не так? Спасибо.

рони 12.08.2019 09:47

_marisha,
может надо поменять
var val = $('.place_elements.active select').val(),
name = $('.place_elements.active select option:selected').html();
на
var val = $('.place_elements.active .place_sections').val(),
name = $('.place_elements.active .place_sections').attr('name');

_marisha 12.08.2019 10:15

рони, спасибо что откликнулись :)
Если сделать так:
$(document).ready(function(){
  $('.place_sections').on('change', function(){
    var val = $(this).val();
    $('.place_elements.active').removeClass('active');
    $('#placeElements' + val).addClass('active');
  });

  $('.placeChoose').on('click', function(){
    var val = $('.place_elements.active .place_sections').val(),
        name = $('.place_elements.active .place_sections').html();
    $.ajax({
      method: 'post',
      url: '/ajax/actions.php',
      data: {action: 'setPlace', place_id: val},
      success: function(data){
        var result = JSON.parse(data);
        if (result){
          whenPlaceChoosen(name); //custom.js
        }
      }
    })
  });
});

Тогда в консоли ошибка:
Uncaught SyntaxError: Unexpected end of JSON input

рони 12.08.2019 10:28

Цитата:

Сообщение от _marisha
name = $('.place_elements.active .place_sections').html();

???

_marisha 12.08.2019 10:32

Прилагаю код файла /ajax/actions.php
if (isset($_POST['action'])){
	switch($_POST['action']){
		case 'setfavplace':
			if (isset($_POST['place_id']) && intval($_POST['place_id'])){
				FavPlaces::setFavs(intval($_POST['place_id']), 'UF_FAV_PLACE');
			}
			break;
    case 'getfavplace':
				echo json_encode(FavPlaces::getFavs());
			break;
		case 'setPlace':
				if (isset($_POST['place_id']) && intval($_POST['place_id'])){
					echo json_encode(FavPlaces::setPlace(intval($_POST['place_id'])));
				}
			break;
		case 'getPlace':
				echo json_encode(FavPlaces::getPlace());
			break;
  }
}

В консоли (вкладка Network):
1) при открытии формы:
id: 211
type: chooseplace
data-trigger: {"class":"btn btn-default pull-right choose_place wplace_choose ch_active","data-event":"jqm","data-param-id":"211","data-param-type":"chooseplace","data-name":"callback1"}

2) при нажатии на "Выбрать":
action: setPlace

laimas 12.08.2019 10:34

Цитата:

Сообщение от _marisha
Unexpected end of JSON input

Значит невалидный JSON получен от сервера.

_marisha 12.08.2019 10:34

Цитата:

Сообщение от рони (Сообщение 511535)
???

У меня опечатка...
Сделано так:
var val = $('.place_elements.active .place_sections').val(),
name = $('.place_elements.active .place_sections').attr('name');

Но в консоли ошибка "Uncaught SyntaxError: Unexpected end of JSON input"

рони 12.08.2019 10:41

_marisha,
var result = JSON.parse(data);, это обычно не нужно!!!
логика немного нарушена, из селектора вы брали код код города и название, как вы ходите получить тоже самое из инпута?

_marisha 12.08.2019 11:12

Цитата:

Сообщение от рони (Сообщение 511541)
_marisha,
var result = JSON.parse(data);, это обычно не нужно!!!
логика немного нарушена, из селектора вы брали код код города и название, как вы ходите получить тоже самое из инпута?

- изначально было другое поле (поле называлось "Место"), которое было в виде выпадающего списка.
Необходимо вместо поля "Место" сделать поле для ввода "Город" ;)

Вывожу в консоль:
var val = $('.place_elements.active .place_sections').val(),
    name = $('.place_elements.active .place_sections').attr('name');
    console.log(val);

Результат undefined

рони 12.08.2019 11:20

_marisha,
может нет .place_elements.active ?
<div class="row place_elements<?=++$counter==1?' active':''?>" id="placeElements<?=$section['ID']?>">

_marisha 12.08.2019 11:41

рони, поидее есть :-?
Изначально было 2 поля (раздел и место. Оба поля выпадающие списки).
На данный момент эти поля не нужны. Нужны поля "Город", "ФИО" и т.д. (обычное поле для ввода).
Вместо поля "Раздел" добавлен input:
<div class="row" id="placeElements">
      	<div class="col-md-12">
      	   <div class="form-group animated-labels input-filed">
      		   <label for="POPUP_SERVICE">Город</label>
             <div class="input">
             	<input type="text" name="" class="place_sections form-control">
            </div>
          </div>
        </div>
      </div>
    </div>

Вместо поля "Место" добавлен input:
<div class="row place_elements active" id="placeElements">
      	<div class="col-md-12">
      	   <div class="form-group animated-labels  input-filed">
      		   <label for="POPUP_SERVICE">ФИО</label>
             <div class="input">
             	<input type="text" name="" class="form-control">
            </div>
          </div>
        </div>
      </div>

рони 12.08.2019 14:17

_marisha,
так проверьте есть ли элемент $('.place_elements.active .place_sections')

_marisha 13.08.2019 06:02

Вложений: 1
Если сделать так
console.log($('.place_elements.active .place_sections').val());
, то в консоли выводится значение заполненного поля.
Если сделать так
console.log($('.place_elements .active .place_sections').attr('name'));
, то в консоли значение атрибута "name"(скрин прилагаю)

рони 13.08.2019 07:32

_marisha,
убрать JSON.parse не пробовали?

laimas 13.08.2019 07:57

Цитата:

Сообщение от рони
убрать JSON.parse не пробовали?

А зачем? Если предполагается, что данные уже объект, то будет ошибка типа Unexpected token in JSON ... Если в параметрах запроса явно не указан ожидаемый тип данных от сервера и сервер не передает заголовок mime типа (что и есть в реальности), то jQuery не обязательно поймет тип данных и примет их как текст. Если явно указан тип или сервером передан заголовок (вот тут не нужен JSON.parse), но данные невалидны, то в success будет null. А ошибка гласит о неожиданном конце данных.

_marisha 13.08.2019 08:51

Кажется ошибка найдена.
Если в
data: {action: 'setPlace', place_id: 54},
поставить численное значение, тогда ошибок нет.
А на данный момент передается строковой значение.
Где конкретно задается тип данных пока неизвестно :-?
Каким образом теперь весь функционал переделать под строковое значение - загадка...

рони 13.08.2019 09:17

_marisha,
data: {action: 'setPlace', place_id: +val},

laimas 13.08.2019 09:50

Цитата:

Сообщение от _marisha
поставить численное значение, тогда ошибок нет

Это как понимать, если все, что принимает сервер, это строки (не считая бинарные данные), а на сервере у вас intval($_POST['place_id'])? Приводить это на стороне клиента к числу нет никакого смысла.

_marisha 13.08.2019 10:21

Цитата:

Сообщение от рони (Сообщение 511588)
_marisha,
data: {action: 'setPlace', place_id: +val},

- в таком случае ошибка с JSON сохраняется :(

_marisha 13.08.2019 10:22

Цитата:

Сообщение от laimas (Сообщение 511589)
Это как понимать, если все, что принимает сервер, это строки (не считая бинарные данные), а на сервере у вас intval($_POST['place_id'])? Приводить это на стороне клиента к числу нет никакого смысла.

- к сожалению, и мне пока не понятно зачем так сделали. Доработка досталась от предыдущих разработчиков.

laimas 13.08.2019 10:37

У вас вообще серверный код странный, если не сказать более. Допустим, что это

if (isset($_POST['place_id']) && intval($_POST['place_id'])){
     FavPlaces::setFavs(intval($_POST['place_id']), 'UF_FAV_PLACE');
}


еще можно трактовать как запрос без ответа, то есть что-то сделать на сервере по запросу клиента и все, а далее все ответы. Но тогда (JSON.parse на клиенте в этом случае не нужен, но нужно учесть как действует JQ при разборе json):

if (isset($_POST['action'])){
    $id = (int)$_POST['place_id']; $data = null;
    switch($_POST['action']){
        case 'setfavplace':
            if ($id) FavPlaces::setFavs($id, 'UF_FAV_PLACE');
            break;
        case 'getfavplace': $data = FavPlaces::getFavs();
            break;
        case 'setPlace':
            if ($id) $data = FavPlaces::setPlace($id);
            break;
        case 'getPlace': $data = FavPlaces::getPlace();
    }
    
    header('Content-type: application/json');
    exit(json_encode($data));
}


Если при этом данные корректны, а значит и ошибок в JSON не будет (собственно в этом случае ошибка была бы уже на сервере). У вас же ошибка указывает на то, что данные json при декодировании неожиданно закончились. Проверить нужно по самое не хочу ответ сервера.

PS. РНР при разборе принятых данных и сам сделает преобразование типов, если число будет числом, а не "числом", заниматься этим на клиенте нет смысла, вы все равно вынуждены проверить тип/преобразовать и проверить.

_marisha 13.08.2019 12:38

laimas, если в файле actions.php сделать так
if (isset($_POST['action']))
{
    switch ($_POST['action'])
    {
        case 'setfavplace':
            if (isset($_POST['place_id']))
            {
                FavPlaces::setFavs($_POST['place_id'], 'UF_FAV_PLACE');
            }
            break;
        case 'getfavplace':
            echo json_encode(FavPlaces::getFavs());
            break;

        case 'setPlace':
            if (isset($_POST['place_id']))
            {
                echo json_encode(FavPlaces::setPlace($_POST['place_id']));
                echo "<pre>" .print_r($_POST,1)."</pre>";
            }
            break;
        case 'getPlace':
            echo json_encode(FavPlaces::getPlace());
            break;
    }
}

Тогда при клике на кнопку "Выбрать" в консоли ошибка "Unexpected token < in JSON at position 4"
Результат:
[action] => setPlace
[place_id] => NaN

laimas 13.08.2019 12:43

Цитата:

Сообщение от _marisha
если в файле actions.php сделать так

Так делать нет смысла, ибо до и после передачи json никакого вывода в браузер не должно быть, иначе вы и получаете такую ошибку. Ошибка же до этого иная, и словно у вас идет поток данных, а потом бабах и EOF.

У вас в РНР коде куча дублированной писанины.

laimas 14.08.2019 00:12

Цитата:

Сообщение от _marisha
[place_id] => NaN

На клиенте проблему решите.

_marisha 14.08.2019 07:57

laimas, если сделать так:
let val = $('.place_sections_block input[name="fio"]').val();
let val1 = $('.place_elements input[name="city"]').val();

Тогда в консоли ошибок нет.
Подскажите, а как можно оба поля поместить в одну переменную (например в val)?

laimas 14.08.2019 08:09

Цитата:

Сообщение от _marisha
Подскажите, а как можно оба поля поместить в одну переменную

В каком смысле одну: если объединить в строку, то это плохо, если передать под одним ключом массив, это можно. Если массив, то это можно сделать двояко:
1) именовать ключ как элемент массива, то есть - data: 'action=setPlace&place_id[]='+val+'&place_id[]='+val1
2) передать под одним ключом как json, то есть - data: {action: 'setPlace', place_id: JSON.stringify(arr)}, где arr массив значений (можно и ручками прописать json для двух значений)

На сервере в первом случае под ключом place_id будет массив из двух значений, во втором случае json, который декодировать и получить массив.

PS. Вы шлете на сервер непотребное и при этом удаляете на нем проверку. Логика странная, тем более что странности есть и вообще в логике приема/ответа.

_marisha 14.08.2019 13:27

laimas,
$(document).ready(function(){
  $('.place_sections').on('change', function(){
    var val = $(this).val();
  });

  $('.placeChoose').on('click', function(){
    let name = $('.place_sections_block input[name="name"]').val();
    let val = $('.place_elements input[name="city"]').val();
    $.ajax({
      type: 'POST',
      url: '/ajax/actions.php',
        data: {action: 'setPlace', 'place_id[]': name, 'place_id[]': val},
      success: function(data){
        var result = JSON.parse(data);
          console.log(data);//true
        if (result){
          whenPlaceChoosen(name); //custom.js
        }
      }
    })
  });
});

В консоли отображаются результаты заполненных полей, но после нажатия на "Выбрать" в файле custom.js console.log(data) приходит значение ["226"]. Хотя в поля вводились значения "ФИО" и "Город"
window.getFavPlaces = function(){
		ajaxAction({action:'getfavplace'}, function(data){
            console.log(data);// приходит 226
			data = JSON.parse(data);

      if (Array.isArray.call(null, data)) {
        data.forEach(function(item){
          if ($('.js_favorite.js_favin[data-id_place=' + item + ']').length){
            $('.js_favorite.js_favin[data-id_place=' + item + ']').addClass('active');
            $('.js_favorite.js_favto[data-id_place=' + item + ']').removeClass('active');
          }
        });
      }
		});
	}

Явно что-то делаю не так...

laimas 14.08.2019 13:43

Цитата:

Сообщение от _marisha
'place_id[]': name, 'place_id[]': val

Так нельзя передать объектом, на сервере будет получено только последнее значение, ибо не могут быть в объекте два одинаковых свойства, как и два одинаковых ключа в массиве. Вот так:

data: 'action=setPlace&place_id[]='+val+'&place_id[]='+val1


Часовой пояс GMT +3, время: 07:19.