Error: Cannot read properties of null reading "checked" - javascript

I'm having trouble fully wiring on my Django applications submit button, it seems that the JS function does not understand which checked boxes to look for
all the console returns are "cannot read properties of null, reading "checked" I'm assuming its something with the function defining but I cannot seem to get it working
Heres the code:
<html>
<head>
{% load static%}
{% block content%}
<link rel="shortcut icon" type="image/png" href="{% static 'IMG/favicon.ico' %}"/>
<link rel="stylesheet" href="{% static 'CSS/bootstrap.min.css' %}">
<link rel="stylesheet" href="{% static 'CSS/jquery-ui.css' %}">
<script type="text/javascript" src="{% static 'JS/bootstrap.min.js' %}"></script>
<title>Task List</title>
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="{% static 'JS/jquery-ui.min.js' %}"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script>
let _csrf = '{{csrf_token}}';
function submit_delete() {
var listItems = $("#list li input");
var checkedListItems = [];
listItems.each(function() {
if (document.getElementById(this.id).checked) {
checkedListItems.push(getTaskId(this.id));
console.log(checkedListItems);
}
})
$.ajax({
headers: { "X-CSRFToken": _csrf },
type: "POST",
url: "/ptm/item_delete",
data: {
'deleteList[]': checkedListItems
}
}).done(location.reload());
}
function getTaskId(str) {
return str.split('-')[1];
}
</script>
</head>
<body>
<div id="logo" class="border-success border border-3 rounded-2" style="width: 61.rem;">
<div class="card-body">
<img class="card-img" src="{% static '/IMG/Logo.png' %}">
</div>
</div>
<div id="taskList" class="card">
{% if task_list %}
<ul class="list-group" id="list">
{% for item in task_list %}
<li class="list-group-item" id='tdList'>
<input id="check-{{ item.id }}" type="checkbox" class="form-check-input me-1" value="">
<label class='d-flex w-100 justify-content-between'>
<h2 class="form-check-label" for="check-{{ item.id }}">{{ item.title }}</h2>
<small class='text-muted'>{{ item.date }}</small>
<input size='3'>
</label>
<h5 class="form-check-label">{{ item.description }}</h5>
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no current tasks assigned to this department.</p>
{% endif %}
</div>
{% csrf_token %}
<div id="taskEnter" class="card-footer">
<div class="d-grid mx-auto">
{% if task_list %}
<button type="button" onclick="submit_delete()" value='delete' class="btn btn-success btn-lg d-grid" value='delete'><i class="">Submit</i></button>
{% endif %}
</div>
</div>
</body>
{% endblock %}
</html>

In the part:
document.getElementById(this.id).checked
document.getElementById(this.id) evaluates to null, which doesn't have any properties, hence the exception you're getting. You're effectively doing null.checked which won't work.
It looks like you're trying to iterate over the checkboxes and determine whether they're checked or not. I'm reasonably confident that this inside the function you wrote will just refer to the window object, so calling this.id won't give you a checkbox id. You have actually already fetched all of the checkboxes (you're iterating over them!) so there's no need to refetch each one manually. Just do:
listItems.each(function(listItem) {
if (listItem.checked) {
checkedListItems.push(getTaskId(listItem.id));
console.log(checkedListItems);
}
})
Note that the function takes as argument the individual listItem (confusingly named since they're actually checkboxes but I'm following your nomenclature here) that each is currently iterating over. Which is what you need.

Try adding a child combinator ('>') to the element selector used in the first line of function submit_delete:
var listItems = $("#list li > input");
- or use a more precise selector of your own devisement.
As posted there appear to be descendant input elements of .list li of form <input size='3'> that don't have an id attribute. Processing these in each returns null from getElementById and throws the error that checked can't be a property of null.
About each
JAuery's each function fires its callback with a this value set to the element being processed during the iteration. The element is also provided to the callback as its second argument. Given elements in HTML should have unique id values:
For elements referred to by this that have id values, using this for the element is simpler than calling getElementById(this.id).
For elements (referred to by this) that do not have an id, !this.id) is a simpler conditional expression than getElementById(this.id)===null.
Filtering out elements that should not be mnatched during selection is preferable to filtering them out later.

Related

Alpine x-transition doesn't work inside jinja2 template for loop

Inside this code, I can get the two divs to toggle when showOriginal is toggled, but the animation simply doesn't work? In this case, summaries are sqlmodel objects rendered by Jinja2.
{% for summary in summaries %}
<div x-data="{showOriginal: true }" class=" flex flex-row">
<div class="ml-4 py-2">
<div>
<p #click="showOriginal = !showOriginal" class="text-xs"><span x-show="showOriginal">Show
Original</span><span x-show="!showOriginal">Show
Summarised</span>
</p>
<div x-show="showOriginal" x-transition.delay.1000ms>
{{summary.title}} </div>
<div x-show="!showOriginal" x-transition.delay.1000ms>
{{summary.paper.title}}</div>
</div>
<a href={{ url_for('summary', summary_id=summary.id) }} class=" md:text-lg text-baseline text-underline">
</a>
<p class="text-sm text-green-300">{{ summary.paper.authors[0].name }},
{{summary.paper.authors[-1].name}} et
al.
</p>
</div>
</div>
{% endfor %}
How I implement the js in base.html, which the above template inhertits from.
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.7.0/dist/alpine.min.js"></script>
<script src="https://unpkg.com/htmx.org#1.8.4"
integrity="sha384-wg5Y/JwF7VxGk4zLsJEcAojRtlVp1FKKdGy1qN+OMtdq72WRvX/EdRdqg/LOhYeV"
crossorigin="anonymous"></script>
{% if DEBUG %} {{ hot_reload.script(url_for('hot-reload')) | safe }}
{% else %}
{% endif %}
<link href={{url_for('static', path='/dist/output.css' )}} rel="stylesheet" />
<title>Openpaper.science </title>
</head>
Take a look at the toggling elements in the devtools. Are Alpine.js transition classes being applied?
If not, it may be because you don't have the defer attribute on your Alpine.js script import.
Should be:
<script defer src="https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.7.0/dist/alpine.min.js"></script>
If the transition classes are being applied and you're just not getting the desired effect with your choice of transition attributes, you may want to customize the classes and/or style the default transition classes differently.
https://alpinejs.dev/directives/transition#applying-css-classes

I can't manage to import and use a javascript function from a .js into a django template. Ideas?

I have a javascript file project_dashboard.js with a few things defined inside of it and an html file where I try to call such function (amont other things).
For some reason, I keep getting the error that the function is not defined at HTMLButtonElement.onclick. What drives me crazy is that the first part of the .js is loaded and works (the css is changed if I click on table). So the script is there, but I can't use the function.
project_dashboard.js
$('table').on('click', 'tr.parent .fa-chevron-down', function(){
$(this).closest('tbody').toggleClass('open');
});
function EnablePositionEdit(position_id) {
const checked_events = []
$("#edit_button_____" + position_id).toggle()
$("#save_button_____" + position_id).toggle()
$("#delete_____" + position_id).toggle()
inputs = document.querySelectorAll(".availability_____" + position_id + " input")
inputs.forEach(input => {
input.removeAttribute("disabled")
})
}
html
{% extends 'action/base.html' %}
{% block extrastylesheets %}
{% endblock extrastylesheets %}
{% block content %}
<head>
{% load static %}
<link rel="stylesheet" href="{% static 'action/css/project_dashboard.css' %}">
<link href="https://cdn.jsdelivr.net/npm/summernote#0.8.18/dist/summernote.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</head>
...
<div id="edit_button_____{{ position.id }}" style="display: block;">
<button class="btn" style="font-size:10px; color: rgb(59, 89, 152);" onclick = EnablePositionEdit('{{ position.id }}')> <i class="fa fa-pencil"></i> </button>
</div>
...
{% endblock content %}
{% block extrascripts %}
<script src="https://cdn.jsdelivr.net/npm/summernote#0.8.18/dist/summernote.min.js"></script>
<script type="text/javascript" src="{% static 'action/js/project_dashboard.js' %}"></script>
<script>
$(document).ready(function() {
$('.summernotable').summernote({
toolbar: [],
});
});
....
</script>
{% endblock extrascripts %}
You have to wrap the function name in quotes, as you do for all attributes, and place the script that contains the function before you call the function.
<script type="text/javascript" src="{% static 'action/js/project_dashboard.js' %}"></script>
<button class="btn" style="font-size:10px; color: rgb(59, 89, 152);" onclick = "EnablePositionEdit('{{ position.id }}')"> <i class="fa fa-pencil"></i> </button>

Django - document.querySelector finds the base.html tags only

I have the django app with traditional base.html approach, which is extended in every other template. However, I have a problem with reaching out html tags which are outside the base.html template.
var myHeading = document.querySelector(".contentfont");
console.log(myHeading);
gives me:
<div class="contentfont">
<!-- JS -->
<script src="/static/js/squad_picker.js" type="text/javascript"></script>
<h1 id="test" class="heading test"> test page </h1>
<div class="container">
<div class="jumbotron">
</div>
</div>
</div>
but when I try for example
var myHeading = document.querySelector(".contentfont > h1");
it always gives me null. The same happens while trying to access anything which is not inside base.html directly by id or class.
I add the part of base.html:
<div class="contentfont">
{% block content %}
{% endblock %}
</div>
and the html which is extending it:
{% extends 'my_app/base.html' %}
{% load static %}
{% block content %}
<!-- JS -->
<script src="{% static 'js/squad_picker.js' %}" type="text/javascript"></script>
<h1 id='test' class="heading test">test page </h1>
<div class="container">
<div class="jumbotron">
</div>
</div>
{% endblock %}
SOLVED: tag should be at the end of the html file...

codemirror - multiple text areas not working

As per the question here Can codemirror be used on multiple textareas?.
I have applied the exact config to my page and neither text areas are being converted to code mirrors.
there are no errors in the console either, im not sure what ive missed?
my code is as follows:
<script src="{% static 'home/scripts/codemirror/codemirror.js' %}"></script>
<link href="{% static 'home/scripts/codemirror/codemirror.css' %}" rel="stylesheet">
<script src="{% static 'home/scripts/codemirror/django/django.js' %}"></script>
<script type="text/javascript">
function editor(id) {
CodeMirror.fromTextArea(id, {
height: "400px",
continuousScanning: 500,
lineNumbers: true
});
}
editor('id_config');
editor('id_remote_config');
</script>
<form id="edit_template" action="" method="post">
{% csrf_token %}
{{ TemplateForm.template_name }}
{{ TemplateForm.config }}
{{ TemplateForm.remote_config }}
<input type='submit' value='Update' />
</form>
the django form renders the text areas with the IDs I have specified
anyone have any ideas?
Thanks
Those textareas don't exist at the time you call editor(). Either move your script tag below the form or call editor() inside a window load event handler

Ajax search feature not working in django App

I'm following a tut from Mike hibbert and have tried to modify it a bit to suit my needs but it's not working. I wanted to use his way because my way was breaking the DRY rule, I had to write search logic for each of my views I thought it might be the order my js But I dont think it is. I could be wrong, as I am fairly new to prgramming. I'm not sure but i think the issue may be with my search being on the nav which I nav in an include. Heres my code
views.py
def search_title(request):
if request.method == "POST":
search_text = request.POST['search_text']
else:
search_text = ''
posts = Post.objects.filter(
Q(title__contains=search_text)|
Q(content__contains=search_text)
)
context = {
"posts": posts
}
return render(request, "posts/ajax_search.html", context)
my nav.html
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="{% url 'posts:list' %}">HiSPANIC HEiGHTS</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<form method="POST" action=" " class="navbar-form navbar-right">
<div class="input-group">{% csrf_token %}
<input type="text" name="search" id="search" placeholder="search" value="{{ request.GET.q }}" class="form-control"
style="width: 350px">
<ul id="search-results">
</ul>
<span class="input-group-btn">
<button type="submit" class="btn btn-primary"><span style="font-size:1.4em" class="glyphicon glyphicon-search"></span> </button>
</span>
</div>
</form>
<ul class="nav navbar-nav">
<li>Home</li>
<li>Sewp</li>
{% if user.is_authenticated %}
<li>Admin</li>
<li>Create</li>
{% endif %}
</ul>
</div><!--/.nav-collapse -->
</div>
base.html
{% load staticfiles %}
<html>
<head>
<title> {% block head_title %} try django 1.9 {% endblock head_title %}</title>
<link rel="stylesheet" href='{% static "css/base.css" %}'/>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css"
integrity="sha384-fLW2N01lMqjakBkx3l/M9EahuwpSfeNvV63J5ezn3uZzapT0u7EYsXMjQV+0En5r" crossorigin="anonymous">
{% include "includes/nav.html" %}
{% include "includes/messages_display.html" %}
<div class="container">
{% if title == "posts" %}
<div class="jumbotron" style="margin-top: 80px">
{% block jumbotron %}{% endblock jumbotron %}
</div>
{% endif %}
{% block content %}{% endblock content %}
</div>
<!-- Latest compiled and minified JavaScript -->
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
crossorigin="anonymous">
</script>
<script src="{% static 'js/ajax.js' %}"></script>
<script src="{% static 'js/jquery.bootstrap-autohidingnavbar.js' %}"></script>
<script>
$("nav.navbar-fixed-top").autoHidingNavbar();
</script>
ajax.js
$(function(){
$('#search').keyup(function() {
$.ajax({
type: "POST",
url: "/posts/search/",
data: {
'search_text': $('#search').val(),
'csrfmiddlewaretoken': $("input[name=csrfmiddlewaretoken]").val()
},
success: searchSuccess,
dataType: 'html'
});
});
});
function searchSuccess(data, textStatus, jqXHR)
{
$('#search-results').html(data);
}
my posts/urls.py
urlpatterns = [
url(r'^$', post_list, name='list'),
url(r'^tag/(?P<slug>[\w-]+)/$', tag_list, name="tag_list"),
url(r'^create/$', post_create, name='create'),
url(r'^sewp$', sewp, name='sewp'),
url(r'^(?P<slug>[\w-]+)/$', post_detail, name='detail'),
url(r'^(?P<slug>[\w-]+)/edit/$', post_update, name='update'),
url(r'^(?P<id>\d+)/delete/$', post_delete, name='delete'),
url(r'^search/', search_title),
]
I see no errors in the network, I've switched back and forth from GET to POST, just trying to tweak things to make it work but nothing has changed. My jquery is from a CDN but I don't think that's an issue, but I am a newb and could be wrong. any help with this will be appreciated
Move your search url definition to the top of the urlpatterns list, so it doesn't get masked by the post_detail wildcards:
urlpatterns = [
url(r'^$', post_list, name='list'),
url(r'^search/', search_title),
url(r'^tag/(?P<slug>[\w-]+)/$', tag_list, name="tag_list"),
url(r'^create/$', post_create, name='create'),
url(r'^sewp$', sewp, name='sewp'),
url(r'^(?P<slug>[\w-]+)/$', post_detail, name='detail'),
url(r'^(?P<slug>[\w-]+)/edit/$', post_update, name='update'),
url(r'^(?P<id>\d+)/delete/$', post_delete, name='delete'),
]
From the docs:
Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL.
And your post_detail regexp certainly matches search/.
I think you may be required to have $ at the end of your search url string.
url(r'^search/$', search_title),
This lets django know it's the end of the string. Unless you've confirmed that you've actually been able to dispatch to the search_title view.

Categories

Resources