Issues with checkboxes functionality on Django and JavaScript interactions

I'm encountering a major issue with checkboxes while developing a ToDo-style application. I aim to have the changes (item_done = False or True) saved when the checkbox is clicked.

To achieve this, I've incorporated a JavaScript script using jQuery for a smoother user experience. However, an error keeps cropping up: clicking on the first item works fine, but upon clicking on the second, the change occurs on the opposite item instead.

I'm struggling to identify where I might be going wrong.

Below is the code snippet:

HTML alongside Django, displaying a list of tasks and items:

   {% extends 'base.html' %}


{% block content %}

<br/><br/><br/>
<div class="container">
  <div class="col-md-6 offset-md-3">
    <div class="row">
      <div class="card border-primary mb-3 text-center" style="max-width: 60rem;">
        <div class="card-header bg-transparent ">{{ task.date }}</div>
        {% if task.image %}
        <img src="{{ task.image.url }}" class="card-img-top" alt="">
        {% endif %}
        <div class="card-body">
          <h3 class="card-header bg-transparent">{{ task.title }}</h3>
          <p class="card-text">{{ task.description }}</p>
        </div>

        <div class="card-header bg-transparent" ><h3>To-do list</h3></div>
        <div class="text-start">
          <br/>
        <ul class="list-group">
        {% if list_items %}
          {% for item in list_items %}
            {% if item.item_done %}
            <li class="list-group-item">
              <input class="form-check-input" type="checkbox" checked="checked" value="{{ item.id }}" id="un-check-box">
              {{ item.title }}
            </li>
            {% else %}
            <li class="list-group-item">
              <input class="form-check-input" type="checkbox" value="{{ item.id }}" id="check-box">
              {{ item.title }}
            </li>
            {% endif %}

          {% endfor %}
        {% else %}
          <p class="text-center">the task list is empty</p>
        {% endif %}
        </ul>
        </div>

        <div>
          <br/>
          <button type="button" class="btn btn-primary">Add new item</button>
        </div>

        <div class="card-header bg-transparent">
        <h3>Notes</h3>
        </div>
        <form>
        <br/>
        <div class="mb-3">
          <textarea class="form-control" id="exampleFormControlTextarea1" rows="3"
          placeholder="type something">
          </textarea>
        </div>
          <button type="submit" class="btn btn-primary">Submit</button>
        </form>
        <div class="card-body">
          <a href="#" class="card-link">Card link</a>
          <a href="#" class="card-link">Another link</a>
        </div>
      </div>
    </div>
  </div>
</div>
<br/><br/><br/>

<script>
// Check if checkbox pressed
$(document).on('click', '#check-box', function(e){
  e.preventDefault();
  $.ajax({
    type: 'POST',
    url: '{% url 'check_boxes' %}',
    data: {
      item_id: $('#check-box').val(),
      csrfmiddlewaretoken: '{{ csrf_token }}',
      action: 'post'
    },

    success: function(json){
      console.log(json)
      document.getElementById("check-box").checked = true;
      location.reload();
    },

    error: function(xhr, errmsg, err){

    }

  });
});

// Uncheck boxes
$(document).on('click', '#un-check-box', function(e){
  e.preventDefault();
  $.ajax({
    type: 'POST',
    url: '{% url 'uncheck_boxes' %}',
    data: {
      item_id: $('#un-check-box').val(),
      csrfmiddlewaretoken: '{{ csrf_token }}',
      action: 'post'
    },

    success: function(json){
      console.log(json)
      document.getElementById("un-check-box").checked = false;
      location.reload();
    },

    error: function(xhr, errmsg, err){

    }

  });
});


</script>

{% endblock %}

JavaScript code:

   <script>
// Check if checkbox pressed
$(document).on('click', '#check-box', function(e){
  e.preventDefault();
  $.ajax({
    type: 'POST',
    url: '{% url 'check_boxes' %}',
    data: {
      item_id: $('#check-box').val(),
      csrfmiddlewaretoken: '{{ csrf_token }}',
      action: 'post'
    },

    success: function(json){
      console.log(json)
      document.getElementById("check-box").checked = true;
      location.reload();
    },

    error: function(xhr, errmsg, err){

    }

  });
});

// Uncheck boxes
$(document).on('click', '#un-check-box', function(e){
  e.preventDefault();
  $.ajax({
    type: 'POST',
    url: '{% url 'uncheck_boxes' %}',
    data: {
      item_id: $('#un-check-box').val(),
      csrfmiddlewaretoken: '{{ csrf_token }}',
      action: 'post'
    },

    success: function(json){
      console.log(json)
      document.getElementById("un-check-box").checked = false;
      location.reload();
    },

    error: function(xhr, errmsg, err){

    }

  });
});


</script>

Python views:

def check_boxes(request):
    if request.POST.get('action') == 'post':
        item_id = int(request.POST.get('item_id'))
        item = get_object_or_404(ToDoItem, id=item_id)
        item.item_done = True
        item.save()
       
        response = JsonResponse({'item': item.item_done,
                                 'item_id' : item_id
                                 })
    return response

def uncheck_boxes(request):
    if request.POST.get('action') == 'post':
        item_id = int(request.POST.get('item_id'))
        item = get_object_or_404(ToDoItem, id=item_id)
        item.item_done = False
        item.save()
        print(item.item_done)

        response = JsonResponse({'item': item.item_done,
                                 'item_id': item_id
                                 })
    return response

Task display along with "to do list." Each item has its own unique identifier.

def view_task(request, pk):
    if request.user.is_authenticated:
        task = Task.objects.get(id=pk)
        list_items = ToDoItem.objects.filter(task=task.id)
        if request.user.id == task.task_user.id:
            return render(request, 'view_task.html', {
                'task': task,
                'list_items': list_items
            })
        else:
            messages.success(request, ("No authorisation!"))
            return redirect('home')
    else:
        messages.success(request, ("You have to be logged in!"))
        return redirect('login')

Models for Task and ToDoItems to aid in deciphering the remaining code.

class Task(models.Model):
    task_user = models.ForeignKey(AppUser, on_delete=models.CASCADE)
    title = models.CharField(max_length=50)
    description = models.TextField(max_length=1000)
    date = models.DateField(default=datetime.datetime.today)
    image = models.ImageField(upload_to='uploads/task/', blank=True)
    is_done = models.BooleanField(default=False)

    def __str_(self):
        """ return object name"""
        return self.title

class ToDoItem(models.Model):
    title = models.CharField(max_length=100)
    task = models.ForeignKey(Task, on_delete=models.CASCADE)
    item_done = models.BooleanField(default=False)

    def __str__(self):
        """return object name"""
        return self.title

Your guidance is greatly appreciated as I strive to understand my mistakes and find solutions.

Answer №1

It seems like the issue you are encountering is due to creating multiple elements on your page with the same id, 'check-box' or 'un-check-box'. To resolve this, consider assigning a specific class to each element and then utilizing document.getElementsByClassName for iteration. If you're using jQuery, you can use $('.class-name').each()

To avoid conflicts, ensure that each element has a unique ID or no ID at all. I hope this information proves helpful!

Answer №2

I implemented some modifications. In the frontend views, I added a logic to manage the state of whether an item is marked as done or not.

def check_boxes(request):
    if request.POST.get('action') == 'post':
        item_id = int(request.POST.get('item_id'))
        item = get_object_or_404(ToDoItem, id=item_id)
        if item.item_done:
            item.item_done = False
            item.save()
        else:
            item.item_done = True
            item.save()

        response = JsonResponse({'item': item.item_done,
                                 'item_id': item_id
                                 })
    return response

In the HTML code, I made some changes:

<ul class="list-group">
{% if list_items %}
  {% for item in list_items %}
    <li class="list-group-item">
      <input type="checkbox" {{ item.item_done|yesno:"checked," }} value="{{ item.id }}"
             class="check-box" id="{{forloop.counter}}">
      {{ item.title }}
    </li>
  {% endfor %}
{% else %}
  <p class="text-center">the task list is empty</p>
{% endif %}
</ul>

And in the jQuery part:

// check boxes
$('.check-box').on('click', function(e){
  e.preventDefault();
  $.ajax({
    type: 'POST',
    url: '{% url 'check_boxes' %}',
    data: {
      item_id: $(this).val(),
      csrfmiddlewaretoken: '{{ csrf_token }}',
      action: 'post'
    },

    success: function(json){
      console.log(json)
      let checkBox
      //below: Uncaught TypeError: checkBox is null
      checkBox = document.getElementById("{{forloop.counter}}")
      if (checkBox.checked === true){
        checkBox.checked = false;
        } else {
        checkBox.checked = true;
        }
      location.reload();

    },

    error: function(xhr, errmsg, err){

    }

  });
});

Now the program correctly updates the item's status in the database but encounters issues when trying to read the unique ID generated by {{forloop.counter}}.

It seems to treat it as empty, leading to the mentioned JavaScript error. I have searched for solutions to this problem without success - using {{forloop.counter}} does not yield the expected results.

If I append text to {{forloop.counter}}, such as "checkbox-{{forloop.counter}}", JavaScript only interprets {{checkbox}} and wrongly assigns the same ID to multiple elements (similar to the previous issue).

What aspect of the code am I overlooking?

Answer №3

I have successfully resolved the issue.

Although it may not be considered professional (or maybe it is), the solution I implemented has effectively addressed most of my problems.

Initially, there were issues with JS not reading either {{foorloop.counter}} or the id, which led me to rely on selecting and deselecting a specific checkbox. However, upon realizing that the item_id was being passed to the JSON and displayed in the control log, I decided to also pass the item value alongside the item id. This allowed me to retrieve the necessary information from the JSON using the getElementById method. With the addition of an if-else condition, the checkboxes on the page now function as intended. I thoroughly tested the solution on another browser, cleared the history, and repeated the process - everything works flawlessly!

Below are the modifications:

HTML and Django tags:

    <li class="list-group-item">
      <input class="form-check-input me-1 check-box" type="checkbox" {{ item.item_done|yesno:"checked," }} value="{{ item.id }}"
        id="{{ item.id }}">
      {{ item.title }}
    </li>

jQuery

$('.check-box').on('click', function(e){
  e.preventDefault();
  $.ajax({
    type: 'POST',
    url: '{% url 'check_boxes' %}',
    data: {
      item_id: $(this).val(),
      csrfmiddlewaretoken: '{{ csrf_token }}',
      action: 'post'
    },

    success: function(json){
      console.log(json)

      let itemId
      itemId = json.item_id
      let checkBox
      checkBox = document.getElementById(itemId)

      if (checkBox.checked === true){
      checkBox.checked = false;
        } else {
      checkBox.checked = true;
        };

      location.reload();

    },

    error: function(xhr, errmsg, err){

    }

  });

});

view

def check_boxes(request):
    if request.POST.get('action') == 'post':
        item_id = int(request.POST.get('item_id'))
        item = get_object_or_404(ToDoItem, id=item_id)
        if item.item_done:
            item.item_done = False
            item.save()
        else:
            item.item_done = True
            item.save()

        response = JsonResponse({'item': item.item_done,
                                 'item_id': item_id
                                 })
    return response

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

I'm having trouble understanding how to utilize startAt and endAt in Firebase version 9

Trying to implement geo querying in my firestore db with the new version of firebase has been challenging. The code examples provided in the documentation reference an older version, making it difficult for me to understand how to use ".startAt" and ".endA ...

Transform a previously escaped backslash into an escaping backslash

I am facing a challenge where the backslashes in my server-generated string are escaped, which is causing some issues for me. Here is an example of the string I have: const s = 'text\\n' Due to the escaped backslashes, the intended fu ...

Validating input in Angular UI Bootstrap Datepicker

I have integrated a datepicker from angular-ui/bootstrap. However, I am facing an issue where the user can freely type in the input field instead of selecting a date. Here is a snippet of my code: session.js session.getDateFormat = function() { ...

Encountered a SyntaxError in vue + webpack regarding an invalid range in character class

I am currently using webpack 4.29.3 and vue.js 2.6.3 to create a simple hello world project. I expected the index.html file to render correctly, but I encountered an error: SyntaxError: invalid range in character class. This error is confusing because I&ap ...

Navigating through hidden input fields in Angular by utilizing the tab key

Seeking a method in Angular to navigate hidden inputs using tab functionality. I have several input forms that display only the text when not on focus. Is there a way to select an input and still be able to tab through the other hidden inputs? Any ideas o ...

Third-party authentication is redirecting AJAX calls within the same domain

Our asp.net core application requires an AJAX call to be made to an IIS 8.0 Server that is protected by CA SiteMinder SSO. When making Get requests using AJAX, the desired response is received. However, when Put or Post requests are made, a 302 response i ...

Using JavaScript, you can easily program a function that will highlight each word in a sentence individually when a

Below is the code I have been working on, but unfortunately it's not functioning properly VIEW FIDDLE HERE MY CODE <button onclick="highlight('fox')">Highlight</button> <div id="inputText">The fox went over the fence< ...

Commands for managing Django applications and its users

When working with Django custom management/commands, I often find myself needing to provide access to my views through these scripts. However, I am facing a dilemma regarding how to do this for authenticated users since I am not utilizing middleware librar ...

restrict the amount of chat history stored

I am currently following a tutorial on how to create a PHP/jQuery based chat application, which you can find here. In summary, this code snippet records messages to a log file: <? session_start(); if(isset($_SESSION['name'])){ $tex ...

Methods for delivering static resources on multiple routes in Express JS

Is there a way to effectively serve static resources for all routes in Express JS? I attempted to serve files with static resources using the following code snippet: app.use(Express.static(`${this.PATH}`)); app.use(Cors()); app.use(Express.json()); app.g ...

What is the best way to conduct synchronous testing of animations in AngularJS version 1.3.15?

Encountering a migration issue with angular-animate.js while transitioning from version 1.2 to 1.3. Here is the animation code snippet: 'use strict'; angular.module('cookbook', ['ngAnimate']) .animation('.slide-down& ...

An Unexpected Appearance of Special Characters in a Python dictionary created from AWS and transmitted to JavaScript via a Django view

In my quest to gather information about my infrastructure, I am working on constructing a dictionary that can be converted into JSON objects. These objects will then be passed to JavaScript for display purposes. I have experimented with using both json.du ...

Store the response token from a Request.post in a variable

To complete a URL, I only need to extract the token provided in the API response. The response body must be saved in a variable for later use. I am currently using Protractor for automated testing, and as part of this process, I need to consume an API tha ...

Transforming data in javascript

I am faced with a data transformation challenge involving extracting information from user input in Apache Superset using metrics. The data is assigned to the variable dataTransformation. {country: "Afghanistan", region: "South Asia", y ...

Manipulate Input Classes by Adding and Removing Them

I am currently using masked JS in some input fields, specifically for telephone numbers. However, I am facing an issue where phone numbers can vary in length, either 10 or 11 digits. I need to switch the class based on whether a checkbox is checked. Here i ...

Is it advisable to optimize your SEO by placing the JavaScript code at the bottom of your webpage?

Is this just an urban legend or is it actually true? I've heard that when web crawlers analyze a webpage, they have a time limit to capture all available code (like html) before moving on to the next page. If the JavaScript code is in the head sectio ...

Styling for older versions of Internet Explorer (IE10 and earlier)

Could it be true that IE 10, 9, and others no longer support conditional statements? Is it also accurate to say that JQuery does not support the browser object above version 1.9? I am facing an issue with CSS rendering differently in Chrome and IE. A Goog ...

Sending a message from a Vue.js application to Contact Form 7 using the Wordpress REST API - a step-by-step guide

I recently added Contact-Form-7 to my WordPress admin panel, which generated an API Endpoint for me at http://localhost/wordpress/wp-json/contact-form-7/v1/contact-forms Attempting to send a POST request to this endpoint using the following code: data() ...

Challenge implementing custom javascript to display categorical/string features on Shiny slider

I'm attempting to design a unique Shiny slider that represents the months of the year. My desired outcome is for the slider to display the names of the months as strings, rather than numeric values where 1 corresponds to January, 2 corresponds to Febr ...

Tips for setting up Django registration with email as the username

Exploring the world of Django, I am currently working on creating a registration form using Django's UserRegistrationForm. The default form requires a username and password, but I'd like to use email instead of username. Does anyone know how I ca ...