0

I am new to AJAX / JSON, and am struggling to parse an AJAX array response into a <select> dropdown.

My result looks fine, but even though I researched quite a few tutorials online and tried various ways of returning the result, every single one of them results in the dropdown menu options showing as undefined.

AJAX result

[{"property_code":"AGGCO","name":"Office Name"}]

Note: there may be as many as 100 entries in the array.

jQuery

$('#unit').on('change', function() {
    var unitID = $(this).val();
    if (unitID) {
        $.ajax({
            type: 'POST',
            url: '../../controllers/admin_addNewUser_units_offices.php',
            data: 'action=unit_office_dropdown&unit_id=' + unitID,
            success: function(response) {
                console.log(response);
                var len = response.length;

                $("#office").empty();
                for (var i = 0; i < len; i++) {
                    var code = response[i]['property_code'];
                    var name = response[i]['name'];

                    $("#office").append("<option value='" + code + "'>" + name + "</option>");

                }
            }
        });
    } else {
        $('#office').html('<option value="">Select Business Unit first</option>');
    }
});

Could someone explain what I am doing wrong please? Thanks

Armitage2k
  • 1,164
  • 2
  • 27
  • 59
  • I don’t see where you’re trying to parse the JSON result… – Sebastian Simon Nov 18 '21 at 14:13
  • `for (var i = 0; i < len; i++)` , iterating through all array results and then via `$(#select).append` add it to the option list, no? – Armitage2k Nov 18 '21 at 14:14
  • `response` is a string, not an array. – Sebastian Simon Nov 18 '21 at 14:15
  • 1
    So what happens when it does not work? Did you add console.log lines to verify response is what you think it is? – epascarello Nov 18 '21 at 14:20
  • 1
    @SebastianSimon all depends on what the content type is. – epascarello Nov 18 '21 at 14:21
  • the above posted result IS the console.log output. – Armitage2k Nov 18 '21 at 14:21
  • So if they are all defined, your back end is not setting the content type on the response so you have a string and jQuery is not going to parse it as JSON. So I would fix the backend to return the right content type. Or live with the fact that you did not set the right content type and parse it yourself on the clientside. – epascarello Nov 18 '21 at 14:23
  • 1
    @Armitage2k Looks like a string. Compare a [string](//i.stack.imgur.com/EHQei.png) and an [actual array](//i.stack.imgur.com/jBys8.png). (My previous comment was an assertion that you should verify yourself; should’ve been more clear…) – Sebastian Simon Nov 18 '21 at 14:25
  • 1
    https://stackoverflow.com/questions/4064444/returning-json-from-a-php-script Probably be the real answer – epascarello Nov 18 '21 at 14:26
  • 1
    Your code as provided [works fine](https://jsfiddle.net/ab81cpv5/). There are ways to reduce, but there's nothing wrong with what you've provided for the js/jquery. What do you get if you do `console.log(JSON.parse(response))`? If it's still a json string then you'll get an object, if jquery auto-parsed it then you'll get `Unexpected token o in JSON at position 1`. That will tell you if your `response` is a string(json) or an object; sounds like it's still a string. – freedomn-m Nov 18 '21 at 14:28
  • 2
    @epascarello bingo, just added `header('Content-type: application/json');` before returning the result via `json_encode` and it works. thank you very much for pointing out the main issue. – Armitage2k Nov 18 '21 at 14:32

1 Answers1

1

Your code looks reasonable - assuming you parse the JSON

It can be simplified

NOTE: If you want "Please select", you can use .html() which will empty the select too - if you do not empty, then next time, you will have the new options added to the previous ones

const response = `[{ "property_code": "AGGCO", "name": "Office Name"}]`; // for testing
const opts = JSON.parse(response); // not needed if you deliver application/json

$("#office")
  .html(new Option("Please select", ""))
  .append(opts
    .map(({ property_code, name }) => new Option(name, property_code)))
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<select id="office"></select>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
  • 1
    Even better: `$("#office").append(opts.map(({ property_code, name }) => new Option(name, property_code)))`. – Sebastian Simon Nov 18 '21 at 14:19
  • Yep, this works. Appreciate the answer! – Armitage2k Nov 18 '21 at 14:22
  • @SebastianSimon Indeed, shorter and without the join - however then we DO need to empty it – mplungjan Nov 18 '21 at 14:23
  • why is it necessary to empty the options first? this would trigger the first result to be the selected one, wouldn't it? – Armitage2k Nov 18 '21 at 14:26
  • @mplungjan Oh, right, forgot about that. But then, `.replaceWith` can be used. – Sebastian Simon Nov 18 '21 at 14:27
  • @Armitage2k You can control which one’s the selected one by specifying the [third or fourth argument of `new Option`](//developer.mozilla.org/docs/Web/API/HTMLOptionElement/Option). – Sebastian Simon Nov 18 '21 at 14:28
  • 1
    If this works, then your original code would also work, as stated in the answer this just provides a shorter/less code version. ... unless your `response` was not an array and was a string, in which case the `JSON.parse` *is* the fix. – freedomn-m Nov 18 '21 at 14:29
  • 1
    If you want "Please select, you can use .html which will empty the select too - if you do not empty, then next time, you will have the new options added to the previous ones – mplungjan Nov 18 '21 at 14:33
  • @freedomn-m I missed to add `header('Content-type: application/json');` before returning the JSON result, so this actually fixed it. But yes, I understand how `JSON.parse` took care of that for me. Thank you! – Armitage2k Nov 18 '21 at 14:35
  • out of curiosity, if I wanted to populate 2 select fields, each with their own array of options, do I need another separate ajax call for the 2nd select field? or can I combine 2 JSON results in one call? – Armitage2k Nov 19 '21 at 04:38