Using Javascript and AJAX in the Fetch()API method: returns no values as a response

Good day, I have attempted to follow the post - “Returning Table Values from User Selection”. My APP does not make use of any forms, but I’ve found that the concepts regarding the use of the Fetch() method make sense for my APP.

<script>

selectAssignment = document.getElementById('assignments');
selectAssignment.addEventListener('change', onChange);

function onChange(e) {
  let lastAssignmentSelected;

  // Returns the text value of the selected Assignment.

  lastAssignmentSelected = e.target.options[e.target.selectedIndex].text;

}


fetch(`http://localhost:8000/getfirstAssignmentSelected/${lastAssignemntSelected}`)
  .then(function(res) {
      return res.json(); 
  })

  
  .then(function(data) {
      
      screening_results_reports = data.screening_results_reports;
      ighid_12046 = data.ighid_12046;
      ighid_12022 = data.ighid_12022;
      amc_099 = data.amc_099;
      sll_qHPV = data.sll_qHPV;
      colpo_LEEP = data.colpo_LEEP;
      clinical_admin_stocktake = data.clinical_admin_stocktake;
      patient_scheduling = data.patient_scheduling;

      //if (data.assignemnts === '________') console.log('True')

      document.getElementById('assignments').innerHTML = data.screening_results_reports;
      document.getElementById('assignments').innerHTML = ighid_12046;
      document.getElementById('assignments').innerHTML = ighid_12022;
      document.getElementById('assignments').innerHTML = amc_099;
      document.getElementById('assignments').innerHTML = sll_qHPV;
      document.getElementById('assignments').innerHTML = colpo_LEEP;
      document.getElementById('assignments').innerHTML = clinical_admin_stocktake;
      document.getElementById('assignments').innerHTML = patient_scheduling;

      console.log('assignments:', lastAssignemntSelected)

  })
  .catch(function(err) {
     console.log(err);
   });
          
</script>

I would like the above script to allow me to access the “id” and field attributes to display fetched data from cell values (User Selections) in a separate HTML table.

Side note: When posting code here, enclose the code between lines of ```. This means you’ll have a line of ```, then the code, then another line of ```. This forces the code to remain properly formatted. Also, please remove unnecessary and excessive leading spaces on the lines. Having code indented 20+ characters is very difficult to read here. (I’ve taken the liberty of editing your original post for this. Please keep these tips in mind for the future.)

You have posted a block of code, and have identified what you would like to do. What is the issue or problem with the code that you are having?

What error messages are you seeing? (Either in the browser console or on the server?)

Note that we are unlikely going to be able to help you much without knowing the structure of the html from which you are trying to extract data.

Also, this block of lines isn’t going to do what I think you might be wanting it to do. The getElementById is going to retrieve a reference to one html element. You’re setting the innerHTML attribute of that element multiple times, where each successive assignment will overwrite the previous assignment.

Hi, thanks for you reply. In future I will make sure I leave the entire line after \. Im not quite sure I pick up on the code indented 20+ characters. Should I have each line of code begin at the beginning of each line?
Ok, first… here is the structure of the html from which I am trying to extract the data…

<table id="table1">
  <thead>
   <tr>
    <th scope="col">Year</th>
    <th scope="col">Month</th>
    <th scope="col">Day of the Week</th>
    <th scope="col">Assignment</th>
  </tr>
  </thead>
    <tbody>
    <tr>
    <td style="border: 1px solid gray;">{% csrf_token %}<select class="form-select"
     onchange="onChange(e)" name="year_date" id="year_date">
    <option value="YearDate1">2025</option>
    <option value="YearDate2">2024</option>
    <option value="YearDate3">2023</option>
  </select>
</td>

This is the structure of the table I would like to display the data into…

<table id="table3" table style="width: 496px">
   <thead>
   <tr>
   <th style="font-size: 70%">MonthDate</th>
   <th style="font-size: 70%">"MonthWeek"<br>"Week 1"</br></th>
   <th style="font-size: 70%">"MonthWeek"<br>"Week 2"</br></th>
   <th style="font-size: 70%">"MonthWeek"<br>"Week 3"</br></th>
   <th style="font-size: 70%">"MonthWeek"<br>"Week 4"</br></th>
   <tr>
   <td><b>Monday</b></td>
   <td id="assignments">{{ lastAssignemntSelected }}</td>
   <td></td>
   <td></td>
   <td></td>
   </tr>
   <tr>
   <td><b>Tuesday</b></td>
   <td></td>
   <td></td>
   <td></td>
   <td></td>
   </tr>
   <tr>
   <td><b>Wednesday</b></td>
   <td></td>
   <td></td>
   <td></td>
   <td></td>
   </tr>
   <tr>
   <td><b>Thursday</b></td>
   <td></td>
   <td></td>
   <td></td>
   <td></td>
   </tr>
   <tr>
   <td><b>Friday</b></td>
   <td></td>
   <td></td>
   <td></td>
   <td></td>
   </tr>
   </thead>
   </table>

As for setting the innerHTML attribute of the element multiple times should I rather have the following:


document.getElementById('assignments').innerHTML = lastAssignmentSelected;

?

The problem I see that I would like to fix first is that despite having been told to setup the API and then using the fetchAPI script - the JSON response does still not come through to populate the table as a cell value. I think I will leave it there and await your response before speaking about some of the other errors that have resulted in the browser. Thank you!!!

Not at the beginning of every line, no. But your original posting had every line indented at least 24 characters, making it effectively unreadable. Your first line should probably start at the beginning of the line, with subsequent lines indented appropriately.

In order to assign values to those individual <td> elements, you either need to provide individual id attributes to every one, or use relative addressing to locate them using the querySelector or use something like getElementsByTagName to iterate over the entire table.

Regardless of the specific function being used, it’s up to your JavaScript code to ensure that the right data is put into the proper element.

The alternative to this would be to have the server render that table for you, and return the table as an HTML fragment that replaces the existing table in the HTML.

For that, we’d need to see a lot more detail. At a minimum, we’d need to see the url definition for the getfirstAssignmentSelected url and the related view. Then we’d need to see what data is actually returned, along with any error messages generated on the server or in the browser console.

Hi. Considering that I would like to code some additional charts that archive the selections made related to specific dates I think it might be a good idea to have the server render a table… then I think the data will be stored and accessible in and from local storage.

Here is the url definition for getfirstAssignmentSelected:


path('getfirstAssignemntSelected/<lastAssignmentSelected>', views.getfirstAssignmentSelected, name='lastAssignmentSelected')

Here is the view for gerfirstAssignmentSelected:


def getfirstAssignmentSelected(request, lastAssignmentSelected):
    name = lastAssignmentSelected.objects.get(assignments = 'lastAssignmentSelected')
    
    response = {
    'screening_results_reports': name.screening_results_reports,
    'ighid_12046': name.ighid_12046,
    'ighid_12022': name. ighid_12022,
    'amc_099': name.amc_099,
    'sll_qHPV': name.sll_qHPV,
    'colpo_LEEP': name.colpo_LEEP,
    'clinical_admin_stocktake': name.clinical_admin_stocktake,
    'patient_scheduling': name.patient_scheduling
    }

    return JsonResponse(response)

As I wait for your next response I will read up on providing individual id attributes to every element so that I know. As well as relative addressing.
As I was saying when I opened the console and looked for JS data that should be returned, there was nothing under ‘Name’. I believe that this method relies more on fetching data / fields created with Django models than on creating a JSON array for example like one of the map() methods I tried - which confused me because even though I think it is possible to iterate over rows and cells, that reproduced table data as opposed to allowing for a user selection to determine what data populates the table.

If you don’t mind, let’s give the HTML fragment a shot, and please do let me know if I understand the functionality there. Thanks

Oh, and in terms of errors that are currently popping up. These aren’t related to this topic I don’t think - they are “GET” errors related to the static files that I’ve been using as a template to design. From my understanding I would need to configure my Apache server correctly to help to fix this anyway.


[14/Aug/2024 09:06:07] "GET / HTTP/1.1" 200 45641
Not Found: /design/tab_link.gif
Not Found: /design/tmp_photo.gif
[14/Aug/2024 09:06:07] "GET /design/tab_link.gif HTTP/1.1" 404 3570
Not Found: /{static 'schedule_app/static/images' %}

I don’t see any element named name in the JsonResponse you are creating. Please post what you are receving

Which method? I don’t know what you’re referring to here.

I was looking for JS responses in the Safari Console - user the Network tab. There is a dropdown bar with the title Name for the name of JS data that is being used in Django. I think I might not know how to go about this though because at one point I attempted the map() method that required a .json array. that doesn’t seem to be a solution since it is complex to target specific values and place them in a specific table cell. I will search online now for how to post you the response that is being received.

All in all. The FetchAPI method is the method I am trying to use.

Are you asking me to console.log using Python in the shell and post that to you ?

I am looking this up now because if I type

console.log('assignments:', lastAssignmentSelected)

the following error pops up:

 File "<console>", line 1, in <module>
NameError: name 'console' is not defined

There must be a lot I am missing about the computer science techniques associated with relative addressing too.

OK. I’ve also picked up an error in the console when filtering by the full URL I intend to use for the FetchAPI method.


 fetch(`http://localhost:8000/getfirstAssignmentSelected/${lastAssignemntSelected}`)

it reads:


Can't find variable: lastAssignmentSelected

does this help ?

Great! But yes, I was looking for you to post the actual data you were receiving.

No. The console.log function is a JavaScript function. You could use it to log the data that you are receiving from the fetch request in the browser.

That’s pretty straight forward - that’s telling you that you don’t have a variable by that name at the point in time at which you are executing that statement.

Taking another look at your JavaScript:

Superficially, I’d say it looks like you’ve got that brace in the wrong location. You want your fetch call to occur within the context of the onChange event, not independent of it. As written (assuming this is complete and correct), the fetch is only going to be done once, when the code is loaded - but at that point in time, the onChange event has not happened, and so you don’t have a lastAssignmentSelected variable defined.

OK. I think this is the data you wanted to see. There is another portion that is supposed include data with a MonthDate field. I would like to have these two fields (assignments + MonthDate) to be the point where selections are saved and recorded in an archive in the web app. Also for those selections to result in relevant output in a performance chart.

{
 "assignments": [
  {
   "screening_results_reports":    "screening_results_reports",
   "ighid_12046": "ighid_12046",
   "ighid_12022": "ighid_12022",
   "amc_099": "amc_099",
   "sll_qHPV": "sll_qHPV",
   "colpo_LEEP": "colpo_LEEP",
   "clinical_admin_stocktake":    "clinical_admin_stocktake",
   "patient_scheduling": "patient_scheduling"
        }
    ]
     
    }

Let me know if this still isn’t what you are looking for.

OK… thanks for identifying the brace being in the wrong place (that took away the error), however “yes” the onChange function does not seem to be making changes. I am going to try and read more on the onChange event itself. I like that way you say - “You want your fetch call to occur within the context of the onChange event, not independent of it.” I think that has to be correct. I am going to think about your comments and all of this over the weekend and hopefully get back in communication with you next week. Many Thanks !!

OH… one last thing… Should I have the beginning declarative section of my JS script equalling the function - i.e.:

document.getElementById('assignments').onChange = function onChange(e) { 
...

and I’m sure it won’t make a difference if this JS script is in its own file, say - client.js ??

Yes it is, thanks.

You’re getting a dictionary, with a key “assignments”, containing a list.
If you’ve assigned this to the name data, then data.assignments is a reference to the list, data.assignments[0] is a reference to the first dict in the list, and data.assignments[0].screening_results_reports is “screening_results_reports”.

If you have multiple entries in the list, the second would be referenced as data.assignments[1], and so on.

You already have that covered:

If you’re talking about moving all of the JavaScript code to a separate file, then yes, it is ok to do that.

I have changed this in the JS script to reference the dictionary that is a list, but am worried that when I try to access these it will still be accessing them in the form of an elementID and that nothing is displayed in the table. I’m not sure if I need to create the object referenced to in my views ??


.then(function(data) {

  data.assignments[0].screening_results_reports = screening_results_reports;
  data.assignments[1].ighid_12046 = ighid_12046;
  data.assignments[2].ighid_12022 = ighid_12022;
  data.assignments[3].amc_099 = amc_099;
  data.assignments[4].sll_qHPV = sll_qHPV;
  data.assignments[5].colpo_LEEP = colpo_LEEP;
  data.assignments[6].clinical_admin_stocktake = clinical_admin_stocktake;
  data.assignments[7].patient_scheduling = patient_scheduling;

I am still quite confused about how Django is receiving data and associated values from the server and that whole interaction.

Below is the view that I have also changed after your previous response. Trying out this as well has not resulted in any data being displayed in the HTML table and I am also not sure how I am going to access the select option values as elements of this table.

data = lastAssignmentSelected.objects.get(assignments = 'lastAssignmentSelected')
 response = {
    'screening_results_reports': data.screening_results_reports,
    'ighid_12046': data.ighid_12046,
    'ighid_12022': data.ighid_12022,
    'amc_099': data.amc_099,
    'sll_qHPV': data.sll_qHPV,
    'colpo_LEEP': data.colpo_LEEP,
    'clinical_admin_stocktake': data.clinical_admin_stocktake,
    'patient_scheduling': data.patient_scheduling
    }

The error msg in the console that pointed me in the direction of an undefined object related to the selectAssignment statement that declares the onChange has gone away after making this change, but I am still not understanding this completely.
Thanks.

Currently I am trying to access the “data” key in the table by:

<td id="assignments">{{ data }}</td>

I have not got it working this way.