2

I have an exercise block with one word and 4 syllables. In my json it looks like this:

{
"main_object": {
"id": "new",
"getExerciseTitle": "TestFrontEnd",
"language": "nl_NL",
"application": "lettergrepen",
"main_object": {
  "title": "TestFrontEnd",
  "language": "nl_NL",
  "exercises": [
    {
      "word": "huisarts",
      "syllables": [
        "Huis",
        "arts",
        "",
        ""
      ]
    },
    {
      "word": "voetbal",
      "syllables": [
        "Voet",
        "bal",
        "",
        ""
      ]
    }
  ]
},
"dataType": "json"
 }
}

I want to loop through these word and syllables, but each word has to remain with their syllables in one exercise block. Right now this is how I tried doing it and I failed big time:

$(document).ready(function () {
$.getJSON('json_files/jsonData_' + ID + '.json', function(json) {


 var exercisetitle = json.main_object.getExerciseTitle;
    $("#getExerciseTitle").val(exercisetitle);


 var exercise = json.main_object.main_object.exercises;
    $.map(exercise, function(exercise, i) {
        $("#addOpdracht").click();
        $(".exerciseGetWordInput_" + i).val(exercise.word) 
         console.log(exercise.syllables);
          $(".sylll" + i).val(exercise.syllables)
    });

  });

});

to visualize it for you, it should look like this

enter image description here

but instead it looks like this enter image description here

so what can I do to get the result I would like to have?

EDIT: The functions where I create the syllable inputs and exercise inputs:

// This is the function that creates the exercise inputs 
function getWordInput(id, cValue) {
 cValue = cValue || '';
 var wInput = $('<input/>', {
'class': 'exerciseGetWordInput_' + id + ' form-group form-control ExerciseGetWordInput',  
'type': 'text',
'name': 'question_takeAudio_exerciseWord['+ exerciseAudioInput +']',
'placeholder': 'Exercise',
'id': 'exerciseGetWordInput',
'required': true
 });
 return wInput;
}


 // This is the function that creates the syllable inputs.
function getWordPartInput(id, cValue){
cValue = cValue || '';
var wpInput = $('<input/>', {
'class': 'form-group form-control syllable sylll' + TT ++,
'type': 'text',
'value': cValue,
'placeholder': 'Syllables',
'name': 'Syllablescounter['+ SyllablesID++ +']'
});
 return wpInput;
}
  • Possible duplicate of [how to create an each loop, but keep the data together](https://stackoverflow.com/questions/51065138/how-to-create-an-each-loop-but-keep-the-data-together) – Ash Jun 27 '18 at 14:56
  • See also: https://stackoverflow.com/questions/51058788/how-to-split-the-commas-in-javascript-jquery-so-the-words-each-go-into-their-res?noredirect=1#comment89109681_51058788 – freedomn-m Jun 27 '18 at 16:00
  • knowing how the `exerciseGetWordInput_` and `sylll` are setup would help. It seems like it should be exerciseGetWordInput_1 and then `syll_1_1`, `syll_1_2`, `syll_1_3`, and `syll_1_4` (the first number represents the exercise and the second the syll) for each exercise. This way you can easily keep exercises and syll's together – Andrew Lohr Jun 27 '18 at 18:28
  • you also might need another loop to loop through the syllables array that is inside the exercise. – Andrew Lohr Jun 27 '18 at 18:29

1 Answers1

2

I don't know how you have your HTML setup but this should get you started in the right direction.

I didn't use $.map because it doesn't look like you want a new array but to do something with your current array. So I instead used Javascripts built in forEach(function(item, index) { .. }) array function. However, I used the Arrow function version.

I also ended up using Template Literals to make creating the jQuery selector a bit cleaner.

const exercises = [{
    "word": "huisarts",
    "syllables": [
      "Huis",
      "arts",
      "",
      ""
    ]
  },
  {
    "word": "voetbal",
    "syllables": [
      "Voet",
      "bal",
      "",
      ""
    ]
  }
];
// forEach((exercise, index) => { .. }) is shorthand for
// forEach(function(exercise, index) { .. });
// See ES6 arrow functions
exercises.forEach((exercise, index) => {
  const word = exercise.word; // Grab the word - huisarts/voetbal
  const syls = exercise.syllables; // Grab the syllables array
  const container = $(`.word-${index+1}`); // Get the correct container based on our index(index)
  const docContainer = document.querySelector(`.word-${index+1}`);
  $('.word', container).val(word); // Assign the word to the first input
  // Foreach syllable
  syls.forEach((syl, i) => {
    $('.syl', container).eq(i).val(syl); // Assign the syllable to the correct input based on our index(i)
    docContainer.querySelectorAll('.syl')[i].value = syl;
  });
});
table,
tr {
  width: 100%;
}

td {
  width: 50%;
  padding: 0 10px;
}

.word-1 input,
.word-2 input {
  display: block;
  width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<table>
  <tr>
    <td class="word-1">
      <input class="word">
      <input class="syl">
      <input class="syl">
      <input class="syl">
      <input class="syl">
    </td>
    <td class="word-2">
      <input class="word">
      <input class="syl">
      <input class="syl">
      <input class="syl">
      <input class="syl">
    </td>
  </tr>
</table>

Edit

Writing selector's with jQuery is easy and the same selector can be used with the Element's querySelector/querySelectorAll functions.

$('.selector') becomes document.querySelector('.selector').

To make the reflection in the snippet above:

// const container = $(`.word-${index}`) becomes
const container = document.querySelector(`.word-${index}`);
..
// $('.word', container).val(word) becomes:
container.querySelector('.word').value = word;
..
// $('.syl', container).eq(i).val(syl) becomes:
container.querySelectorAll('.syl')[i].value = syl;

Creating an element in jQuery is a bit easier as well:

var TT = 0;

function getWordPartInput(id, cValue) {
  cValue = cValue || '';
  var wpInput = $('<input/>', {
    'class': 'form-group form-control syllable sylll' + TT++,
    'type': 'text',
    'value': cValue,
    'placeholder': 'Syllables',
    'name': 'Syllablescounter[' + SyllablesID++ + ']'
  });
  return wpInput;
}

$('body').append(getWordPartInput(1, 1));

function getWordPartInput(id, cValue) {
  cValue = cValue || '';
  var wpInput = document.createElement('input');
  wpInput.classList.add('form-group', 'form-control', 'syllable', 'sylll', TT++);
  wpInput.type = 'text';
  wpInput.value = cValue;
  wpInput.placeholder = 'Syllables';
  wpInput.name = 'Syllablescounter[' + id++ + ']';
  return wpInput;
}

document.body.append(getWordPartInput(1, 2));

As for ditching jQuery's ajax in favor of vanilla JS this answer does a pretty good job of explaining.

Community
  • 1
  • 1
Wild Beard
  • 2,919
  • 1
  • 12
  • 24
  • I editted the post so you could get a better view of it, I don't really use HTML to create input fields or anything. I try to do it as much as possible with jquery and javascript. I hope I provided enough info with the edit I made. Also, is it possible NOT to use the script of ajax/libs.jquery? That bumps into other functionalities of my web. I still appreciate the work you just put in a lot. So thank you very much for that @Wild Beard –  Jun 27 '18 at 21:27
  • @JJShaw you don't have to use jQuery but it makes life a lot easier. Especially when creating new elements. The only jQuery I used was the `$('selector')` and `.eq(index)` which can easily be done without jQuery. As for not using jQuery's ajax - you could, but again, it makes life a hell of a lot easier. As for an alternative though checkout [this post](https://stackoverflow.com/questions/1973140/parsing-json-from-xmlhttprequest-responsejson) – Wild Beard Jun 27 '18 at 21:59
  • Not saying your code is flawed or anything, it's most likely my fault... But I seem to get: "Uncaught TypeError: Cannot read property 'querySelector' of null" whenever I try to use the code. Could you / do you have time to clarify a bit more about your code? I can show you what I have tried, but that would make it a mess in the original post.. So yeah. I still appreciate the effort very much –  Jun 28 '18 at 10:45
  • @JJShaw sounds like `document.querySelector` is failing. Make sure you spelled `document` correctly. `document` is global so it should be available to you anywhere in your code. I've also updated my snippet to show both jQuery and usage of `document` working properly. – Wild Beard Jun 28 '18 at 14:35