-1

I'm trying to send a JSON Object to my back-end. Basically what I'm trying to do is get the input of 2 textfields and then a list of all selected text boxes. My javascript code so goes like this:

function insertNewHero() {
        var selectedAbilities = [];
        $('#newhero input:checked').each(function() {
            selectedAbilities.push({
                "id": $(this).value,
                "ability": $(this).textContent
            });
        });

        var superhero = {
            "name": document.getElementById("name").value,
            "surname": document.getElementById("lastName").value,
            "abilities": selectedAbilities
        }

        $.ajax({
            type: "POST",
            contentType: 'application/json; charset=utf-8',
            dataType: 'json',
            url: "/insertNewHero",
            data: JSON.stringify(superhero),
            success: function (result) {
                // other stuff
            }
        });

I'm really not an expert yet with javascript, but from what I've found from other anwers and posts this is what I could put together and thought it could actually work. The back-end part is working fine, as I tested it with PostMan and perfectly works fine. This is what the JSON, I;m sending from PostMan, looks like:

{
    "name": "Wanda",
    "surname": "Maximoff",
    "abilities": [
            {
                "id": 4,
                "ability": "Telechinesis"
            },
            {
                "id": 3,
                "ability": "Flight" 
            }
        ]
}

What could be wrong in the JavaScript code?

Here is a sample of one of the textfields and one of the checkboxes:

<div class="form-group">
     <label for="lastName">Last Name</label>
          <input type="textfield" class="form-control" id="lastName" placeholder="Last Name" required>
</div>
<div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" style="background: #bf0000; color: #bf0000; border: solid #bf0000" id="InsertFlight">
    <label class="custom-control-label" for="InsertFlight" value="3">Flight</label>
 </div>

Apparently the javascript code is not parsing correctly the value and ids of the checkboxes. How can I make of the checkboxes HTML content, a JSON array correctly formatted

L_Cleo
  • 1,073
  • 1
  • 10
  • 26
  • 2
    Google that error. It doesn't appear to be a JS issue: See [this](https://stackoverflow.com/questions/2302802/how-to-fix-the-hibernate-object-references-an-unsaved-transient-instance-save) and [this](https://stackoverflow.com/questions/45778937/transientpropertyvalueexception-object-references-an-unsaved-transient-instance). It's also worth noting that you can improve the JS with `map()`: https://jsfiddle.net/RoryMcCrossan/vgxwrnmq/ – Rory McCrossan Jan 24 '20 at 10:00
  • It is. That error comes up because the object is null so there is no Id to associate the already existing abilities to the new hero. I've already tried sending the same JSON structure through postman and works perfectly fine. So there is some kind of problem with the building of the JSON in javascript but I can't figure out where the problem could be – L_Cleo Jan 24 '20 at 10:02
  • 1
    Ok, in that case open dev tools and check the body of the request you send to ensure it's valid JSON and in the same format that you use in Postman – Rory McCrossan Jan 24 '20 at 10:04
  • You don't need to do `JSON.stringify(superhero)` on your data, you can pass `superhero` data as is and it should work fine with the backend – Sarfraaz Jan 24 '20 at 10:08
  • 1
    @Sarfraaz Without stringifying, jQuery will turn the object into a querystring instead. Anyway, here's live code and the request seems fine: https://jsfiddle.net/khrismuc/4fL7tujv/ –  Jan 24 '20 at 10:10
  • Ok so that gave me a good heads up. Sorry about that but like I said I don't really code too much in front-end. Anyways debugging it I see that the ability is undefined as well as the id... So I guess there is something wrong when creating the list. – L_Cleo Jan 24 '20 at 10:11
  • 1
    Can you add the HTML? Because a checkbox usually has no value or textContent. –  Jan 24 '20 at 10:11
  • Done, so the texbox is working fine because in the prepared Json I can see that the name and the lastname are actually put in correctly. Adding to the fact of undefined properties, the abilities array have this structure: 0 : { ... }, 1 : { ... } which is of course not what I want, there should be no indexes – L_Cleo Jan 24 '20 at 10:16
  • 1
    It's an array; it will always have indexes. – Rory McCrossan Jan 24 '20 at 10:21
  • I know, but is there any other way to make a JSON array without indexes? – L_Cleo Jan 24 '20 at 10:22
  • 1
    I updated the fiddle to work with the HTML: https://jsfiddle.net/khrismuc/4fL7tujv/ –  Jan 24 '20 at 10:31

1 Answers1

1

The main issue seems to be extracting the abilities from the HTML.
To do that, iterate over all checked checkboxes, then use jQuery functions like .closest() or .find() to grab the <label>. From there you can extract the required information.

function insertNewHero() {
  var abilities = {};
  $('#newhero .custom-checkbox input:checked').each(function() {
    const $label = $(this).closest("div").find("label");
    abilities[$label.data("id")] = $label.text();
  });

  var superhero = {
    name: "Wanda",
    surname: "Maximoff",
    abilities
  }
  
  console.log(superhero);

  // send data to backend
}

$('#newhero').on("submit", function(e) {
 e.preventDefault();
  insertNewHero();
});
#newhero, .form-group {
  padding: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">

<form id="newhero">
  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" style="" id="InsertFlight">
    <label class="custom-control-label" for="InsertFlight" data-id="3">Flight</label>
  </div>
  <div class="custom-control custom-checkbox">
    <input type="checkbox" class="custom-control-input" style="" id="InsertTelekinesis">
    <label class="custom-control-label" for="InsertTelekinesis" data-id="4">Telekinesis</label>
  </div>
  <div class="form-group">
    <input type="submit">
  </div>
</form>