-2

I'm trying to send my car value in API, the value comes from below html.

And then, I want to send this value in API using AJAX.

And then I want to display all the models as I displayed cars.

$(document).ready(function() {
  $('#cars').on('change', function() {
    $.ajax({
      'url': 'https://us-central1-pitstop-8258d.cloudfunctions.net/models',
      'type': 'GET',
      'dataType': 'json',
      'data': {
        'make': $('#cars').val()
      },
      'success': function(response) {
        if (response.results) {
          var html = '';
          html += '<select name="cars2" id="cars2">';
          for (var i = 0; i < response.results.length; i++) {
            html += '<option value="' + response.results[i] + '">' + response.results[i] + '</option>';
          }
          html += '</select>';
          $('#results').html(html);

        }
      }
    });
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<select name="cars" id="cars">
  <option value="Acura">Acura</option>
  <option value="Audi">Audi</option>
  <option value="BMW">BMW</option>
  <option value="Tesla">Tesla</option>
</select>

<div id="results"></div>
CherryDT
  • 25,571
  • 5
  • 49
  • 74
  • 3
    so what doesn't work here ? – Swati Apr 19 '21 at 05:49
  • 1
    Other than failing to escape the HTML properly, it seems to work as intended (assuming the API returns results in the format you expect and your HTML has an element with `id="results"`), so what is the problem? You only wrote what you wanted to do, not what you actually need help with while doing it. – CherryDT Apr 19 '21 at 05:54
  • 1
    After I edited your post so the code can be run from it directly, it becomes clear what the issue is. Check your browser's console, you'll see the message `Access to XMLHttpRequest at 'https://us-central1-pitstop-8258d.cloudfunctions.net/models?make=Audi' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.`, so you cannot access this API directly from frontend JavaScript, you need to access it from your backend server code instead. (Also, you should probably add `$('#cars').change()` so it will also load intially.) – CherryDT Apr 19 '21 at 06:00
  • Please edit your question to contain more details - what is working, what is not? Where **exactly** are you searching for help? What have you tried to fix whatever problem you are facing? – Nico Haase Apr 19 '21 at 06:00

1 Answers1

2

It's not clear what the actual problem is that you are asking about, because you just described what you want to do and showed some code, but not what the actual issue with it is - what does happen compared to what you expect, is there an error, etc.

I've edited your question so the code is wrapped in a snippet which can be executed, and from this I figured what the issues are - but next time it would be great if you could do that yourself and describe where exactly you run into a problem and how exactly this problem manifests itself.


1: The API you are attempting to use doesn't allow accessing it from front-end JavaScript directly, because no CORS headers are present. If you look into the browser's devtools console, you'll see that it shows you a corresponding error:

Access to XMLHttpRequest at 'https://us-central1-pitstop-8258d.cloudfunctions.net/models?make=Audi' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

To solve this problem, you need to have your server-side code on your backend make the request, and call this backend API from your frontend, instead of having the frontend make the request itself. See this answer for an example.


2: On initial page load, no API call is made because it reacts only on changing the selection, not on the initial selection. You can force it by adding $('#cars').change() at the end of the code so it triggers a change event on page load too.


3: If you look at what the API returns, you'll see the structure is like this:

{
  "success": true,
  "data": [
    {
      "model": "100"
    },
    {
      "model": "80"
    },
    {
      "model": "90"
    },
    {
      "model": "A3"
    },
    {
      "model": "A3 Sportback e-tron"
    },
    ...
]

The array with the actual items is called data, not results.


4: The individual result items are an object with a property model, not a string. So your current could would just show [object Object] for every item. You need to access the model property instead: response.data[i].model


5: You are not escaping the text that you insert into your HTML. What if a car model would include a " doublequote? It would break your value attribute since it's delimited by doublequotes - just as an example. It would be better to only insert a <select> and then to add the <option> elements individually using mySelect.append($('<option>').attr('value', model).text(model)). Alternatively, you can use the $('<i/>').text(value).html() idiom to escape the values when embedding them into your HTML string.

You should make it a habit to always do this and immediately notice when there is anything not properly escaped, because in cases where the inserted data comes from untrusted sources such as user input, you not only can break your page/layout but also introduce a cross-site scripting (XSS) security vulnerability.


In general it looks as if you hadn't yet figured out how to use browser devtools to see errors and to debug and step through JavaScript code. Check out this devtools crash course!

CherryDT
  • 25,571
  • 5
  • 49
  • 74