Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Как последовательно считывать данные json файла и отдавать в форму? (https://javascript.ru/forum/misc/75278-kak-posledovatelno-schityvat-dannye-json-fajjla-i-otdavat-v-formu.html)

giwuf 18.09.2018 20:23

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

Собираю массив через
Код:

data.forEach(function(item) {});
, но если внутрь поместить функцию answers, то абсолютно все ответы ждя разных вопросов просто отобразятся на одной страницы.
Как можно реализовать задуманное?

Фидл здесь - http://jsfiddle.net/qxrognd6/

$(function() {
  var vote = {};
  $('#ok').click(function() {

    $.get(poll.json, function(data) {

      // фактически данные poll.json хранятся в таком виде
      //data = [{"id":"1", "question":"Какую марку предпочитаете?", "answers":["honda", "bmw", "volvo"]}, {"id":"2", "question":"Цвет авто?", "answers":["black", "red", "blue"]}

      data.forEach(function(item) {

        vote.id = item.id;
        vote.question = item.question;
        vote.answers = item.answers;

      });

      answers();
    });

    appearance('#start', '#content');
    return false;

  });

  var appearance = function(slide, content) {
    $(slide).hide('fast', showNewContent);
    $('#load').remove();
    $('#wrapper').append('<span id="load">LOADING...</span>');
    $('#load').fadeIn('normal');

    function showNewContent() {
      $(content).show('normal', hideLoader());
    }

    function hideLoader() {
      $('#load').fadeOut('normal');
    }
  };
  var answers = function() {
    for (var i = 0; i <= vote['answers'].length - 1; i++) {
    var form = $('#vote');
    var answers = form.find('.answers');
    form.parent().find('.question').text(vote['question']);
      answers.append('<div class="radio">' +
        '<label>' +
        '<input type="radio" name="poll" value="' + (i + 1) + '">' +
        vote['answers'][i] +
        '</label>' +
        '</div>');
    }
  };
});

<div id="start">
<a id='ok' href=''>Поехали</a>
</div>
<div id="content">
<h4 class="question">Вопрос</h4>
<form id="vote" action="vote.php" method="POST">
   <div class="answers"></div>
   <button type="submit" class="btn btn-default">ответить</button>
</form>
</div>

Код:

#content {
        display: none;
}
#load {
 display: none;
 position: absolute;
 right: 10px;
 top: 10px;
 width: 43px;
 height: 11px;
 text-indent: -9999em;
}


Nexus 18.09.2018 20:33

А вывести все вопросы на страницу в одной форме и последовательно их показывать - не вариант?

giwuf 18.09.2018 21:52

Цитата:

Сообщение от Nexus (Сообщение 494987)
А вывести все вопросы на страницу в одной форме и последовательно их показывать - не вариант?

Nexus,
вариант. А как это сделать? в смысле последовательно показывая и скрывая предыдущий вопрос? Прошу прощения, не дописал 3 строчки кода в функцию answers. Исправился.

Я правильно вас понял, что вы предлагаете каким-то образом выводить и последовательно скрывать вот этот перечень вопросов?

<form id="vote" action="#" method="POST">
<div id="content">
<h4 class="question">Какую марку предпочитаете?</h4>
             <div class="answers">
               <div class="radio"><label><input type="radio" name="poll" value="1">honda</label></div>
               <div class="radio"><label><input type="radio" name="poll" value="2">bmw</label></div> 
               <div class="radio"><label><input type="radio" name="poll" value="3">volvo</label></div>
                <button type="submit" class="btn btn-default">Ответить</button>
</div>
<h4 class="question">Цвет авто?</h4>
             <div class="answers">
               <div class="radio"><label><input type="radio" name="poll" value="1">black</label></div>
               <div class="radio"><label><input type="radio" name="poll" value="2">red</label></div> 
               <div class="radio"><label><input type="radio" name="poll" value="3">blue</label></div>
                <button type="submit" class="btn btn-default">Ответить</button>
</div>
</div>
</form>

рони 18.09.2018 22:26

giwuf,
в строке 2 добавить индекс = 0, по клику увеличивать и показывать вопрос согласно индексу

laimas 19.09.2018 05:59

giwuf, если данные в json и их количество в наборе равно (по три кнопки), то нужно не строить постоянно html код, а заполнять значениями данных одних и тех же кнопок, двигаясь по массиву json.

giwuf 19.09.2018 09:27

Цитата:

Сообщение от рони
giwuf,
в строке 2 добавить индекс = 0, по клику увеличивать и показывать вопрос согласно индексу

Спасибо рони, вроде бы и улавливаю смысл сказанного, но не до конца понимаю, как в зависимости от индекса показывать вопрос и что делать в этом случае с foreach ?
$(function() {
  var index = 0;
  var vote = {};
  $('#ok').click(function() {
     index++;

    $.get(poll.json, function(data) {

      data.forEach(function(item) {

        vote.id = item.id;
        vote.question = item.question;
        vote.answers = item.answers;

      });

      answers();
    });

    appearance('#start', '#content');
    return false;

  });
});


Цитата:

Сообщение от laimas
giwuf, если данные в json и их количество в наборе равно (по три кнопки), то нужно не строить постоянно html код, а заполнять значениями данных одних и тех же кнопок, двигаясь по массиву json.

laimas, да согласен с вами, можно отформатировать и внедрить html вначале, у меня основной затык в том как заполнять значениями данных одних и тех же кнопок, двигаясь по массиву json, которые будут переключаться по кнопке ответить

рони 19.09.2018 09:41

Цитата:

Сообщение от giwuf
что делать в этом случае с foreach

выкинуть, зачем он нужен?

рони 19.09.2018 09:50

giwuf,
получили json, вывели все блоки на страницу, показали только блок с индексом 0.
по клику на btn скрыли блок с текущим индексом, увеличили индекс, открыли следующий блок

рони 19.09.2018 09:55

giwuf,
медитировать после создания всех полей тут
форма пошаговая обязательные поля

Nexus 19.09.2018 09:59

https://jsfiddle.net/vLtrgok1/

giwuf 19.09.2018 10:14

Цитата:

Сообщение от рони
giwuf,
получили json, вывели все блоки на страницу, показали только блок с индексом 0.
по клику на btn скрыли блок с текущим индексом, увеличили индекс, открыли следующий блок

Спасибо, рони. Вот по такому принципу?
$(function(){

var vote = {};
var index = 0;
var item;
$('#ok').click(function(){

$.get(pathToPolls, function(data) {

item = JSON.parse(data);
answers(); //выводим блоки с вопросами

});

if(index) {
          vote['id']= item[index]['id'];
  vote['question']=item[index]['question'];
  vote['answers']=item[index]['answers'];
show_answers(); //показываем блок с вопросами
}
else {
          vote['id']= item[index]['id'];
  vote['question']=item[index]['question'];
  vote['answers']=item[index]['answers'];
show_answers();
index++;
}

});
});

рони 19.09.2018 10:34

giwuf,
зачем вам vote ?

giwuf 19.09.2018 10:38

рони и Nexus, спасибо большое за помощь - изучу и постараюсь внедрить!

рони 19.09.2018 11:21

giwuf,
item = JSON.parse(data); ???
это jquery, data уже обьект , а не строка.
item = data;

giwuf 19.09.2018 12:36

Цитата:

Сообщение от рони (Сообщение 495089)
giwuf,
item = JSON.parse(data); ???
это jquery, data уже обьект , а не строка.
item = data;

рони, понял, спасибо
А в случае с примером от Nexus
Цитата:

Сообщение от Nexus
https://jsfiddle.net/vLtrgok1/

идет работа с константой
const data = [{
    "id": "1",
    "question": "Какую марку предпочитаете?",
    "answers": ["honda", "bmw", "volvo"]
}, {
    "id": "2",
    "question": "Цвет авто?",
    "answers": ["black", "red", "blue"]
}];


И теперь вытащить данные с настоящего файла json, как было раньше не удается.
Так:
$.get(data.json, function(data) { });

Или так
$.getJSON(data.json, function( data ) {
  var items = [];
  $.each( data, function( key, val ) {
    items.push( "<li id='" + key + "'>" + val + "</li>" );
  });
});

Показывает ошибку и данные не подтягиваются. Снова что-то недопонимаю?

Иои нужно константу сохранять как файл json и подключать так и потом парсить?
<script type="text/javascript" src="file.json"></script>

рони 19.09.2018 12:42

Цитата:

Сообщение от giwuf
data.json

Цитата:

Сообщение от giwuf
file.json

:-?

Nexus 19.09.2018 12:55

giwuf,
<form id="vote" action="#" method="POST">
    <div id="content">
        <div class="pattern">
            <h4 class="question">{% question %}</h4>
            <div class="answers">
                <div class="radio"><label><input type="radio" name="poll[{% id %}]" value="{% answer.value %}">{% answer.title %}</label></div>
            </div>
        </div>
    </div>
    <div><button type="submit" class="btn btn-default">Ответить</button></div>
</form>
<script>
	$.getJSON('/path/to/you-json',function(data){
		data=(typeof data==='string')?JSON.parse(data):data;
		
		const content = document.getElementById('content');
		const patternNode = content.querySelector('.pattern');

		patternNode.classList.remove('pattern');
		const pattern = patternNode.outerHTML;
		patternNode.parentNode.removeChild(patternNode);

		data.forEach(function(question, index) {
			content.insertAdjacentHTML('beforeEnd', pattern.replace(/{%\s?question\s?%}/gim, question.question));
			const questionNode = content.lastChild;
			questionNode.dataset.index = index;
			questionNode.style.display = 'none';
			const answers = questionNode.querySelector('.answers');
			const answer = answers.querySelector('.radio').outerHTML;
			answers.innerHTML = question.answers.map(function(title, value) {
				return answer
					.replace(/{%\s?id\s?%}/gim, question.id)
					.replace(/{%\s?answer.title\s?%}/gim, title)
					.replace(/{%\s?answer.value\s?%}/gim, value);
			}).join("\n");
		});

		let currentQuestionIndex = 0;
		const questions = [].slice.call(content.querySelectorAll('[data-index]'));
		questions[0].style.display = 'block';

		document.querySelector('#vote [type="submit"]').addEventListener('click', function(e) {
			questions[currentQuestionIndex].style.display = 'none';
			if (++currentQuestionIndex >= questions.length)
				return;

			e.preventDefault();
			questions[currentQuestionIndex].style.display = 'block';
		});
	});
</script>

рони 19.09.2018 13:14

:-? одно name на все блоки?

giwuf 19.09.2018 13:21

О, Nexus и рони, спасибо большое! Готов расцеловать!
Расставлю плюсы как только откроется у меня такая возможность.
2 последних мини-вопроса:
1 - выбранные ответы на вопросы на каждой итерации передается в файл, который укажу в форме в поле action="" или как-то по другому
2 - чтобы добавить нумерацию вопросов по id из файла - мне нужно
data.forEach(function(question, index) {
//приплюсовать к заголовку вопроса параметр index - так?
});

giwuf 19.09.2018 13:22

Цитата:

Сообщение от рони
одно name на все блоки?

А это чревато?

Nexus 19.09.2018 13:28

Цитата:

Сообщение от рони
одно name на все блоки?

Таки да... поправил.

giwuf,
1. выбранные ответы передаются на сервер после того, как пользователь ответит на все вопросы;
2. да, можно и так.

upd. п.1 обновил.

рони 19.09.2018 13:40

Цитата:

Сообщение от giwuf
А это чревато?

что на сервер отправлять? при нормальных name будет обычная форма а так танцы с бубнами
Цитата:

Сообщение от giwuf
- выбранные ответы на вопросы на каждой итерации передается в файл


giwuf 19.09.2018 15:32

Nexus и рони, понял, отлично, спасибо!


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