Transferring a JS Array to Python using AJAX & Flask - not working - javascript

I am experiencing some problems with my code. My data loader to python isn't working. Here is my HTML site (using Jinja syntax from a base.html):
{% extends 'base.html' %}
{% block head %}
<title>PPO Count</title>
{% endblock %}
{% block body %}
<!-- Header -->
<div class="header">
<h2 class='title'>Prototype 1: Pet Owner Viz</h2>
</div>
<!-- Button Panel-->
<!-- Vis Box -->
<div class='canvas'>
<div class="container">
<div class='button-box'>
<button id='Bx' type="button" onclick='toggleClickedBuz("Bx", "Bx")'>Bx</button>
<button id='By' type="button" onclick='toggleClickedBuz("By", "By")'>By</button>
<button id='Bz' type="button" onclick='toggleClickedBuz("Bz", "Bz")'>Bz</button>
<button id='loadData'>Load Data</button>
</div>
<div class='viz-box'>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="/static/js/main.js"></script>
{% endblock %}
Notice the buttons? What occurs is that onclick, it goes into an array using JS. In sum this function deletes duplicate entries and changes the colour of the buttons on screen to highlight their selection.
const vizBox = d3.select('.viz-box');
const svg = vizBox.append('svg');
// Create button click array
var clickedBusinesses = [];
function toggle(business) {
clickedBusinesses[business] = !clickedBusinesses[business];
};
function getClickedBusinesses() {
return Object.keys(clickedBusinesses).filter(key => clickedBusinesses[key]);
};
// Update array and change button colour to reflect selection
function toggleClickedBuz( bizStr , id ) {
if(clickedBusinesses.includes(bizStr)){
// removing duplicate element from that array, dependant on button pressed
clickedBusinesses = clickedBusinesses.filter( cb => cb !== bizStr );
document.getElementById( id ).style.backgroundColor='white';
}else{
// else push it to the array
clickedBusinesses.push(bizStr)
document.getElementById( id ).style.backgroundColor='red';
}
var json_string = JSON.stringify(clickedBusinesses)
console.log(json_string)
};
window.onload = function() {
d3.select('loadData').onclick = function() {
doWork()
};
}
function doWork() {
$.post('receiver', json_string, function() {
});
event.preventDefault();
}
button id='loadData' isn't working, I can't get my jsonified JS array into python. Any thoughts?

d3.select does not return a native DOM node, it returns a so called d3-selection that doesn't know anything about onclick. Instead, you should use the .on method of a d3-selection to register event listeners as described here: https://github.com/d3/d3-selection#handling-events
Alternatives:
Instead of using d3 to select elements, use the native .querySelector method: document.querySelector('#loadData').onclick = ....
Or use jQuery for it: $('#loadData').on('click', ...).

Related

Hide and show elements inside Django HTML template

I have 2 buttons orders, and suppliers., and want to show data in a Django web app when the corresponding button is clicked. To do this my home.html looks like
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(".button_order").click(function(){
$(".myorders").show();
$(".mysupplier").hide();
});
$(".button_supplier").click(function(){
$(".myorders").hide();
$(".mysupplier").show();
});
});
</script>
syle.css looks like;
.myorders,
.mysupplier{
font-size: 25px;
display: none;
}
This works perfectly fine until I use normal data like;
<body>
{%block content %}
<button class="button_order" >ORDERS</button>
<button class="button_supplier" >SUPPLIER</button>
<p class="myorders" >
This is my order
</p>
<p class="mysupplier">
my supplier is cool
</p>
</body>
But when I try to use data into <p class="mysupplier"> or <p class="myorders" > from my databases, the hide property no longer works, like below part.
<p class="myorders">
{% for element in orders %}
{% for key,val in element.items %}
<ul><li>{{key}}:{{val}}</li></ul>
{% endfor %}
<hr class="new1">
{% endfor %}
</p>
I should get Order data from database only when ORDER button is clicked, but my server shows all data from before without even clicking the button. How to maintain hide and show the property of my data.
my views.py looks like
from django.shortcuts import render
client = MongoClient("mongodb://localhost:27017/")
db=client.inventory_data
def home(request):
collection_data_1 = db['orders']
orders = list(collection_data_1.find())
collection_data_2= db['suppliers']
suppliers = list(collection_data_2.find())
return render(request,'home.html',{'orders': orders,'suppliers':suppliers})
The loop in template is executed when rendering template. You pass all your data from view to template. if you just want to hide it from display add to your js:
<script>
$(document).ready(function(){
$(".mysupplier").hide();
$(".myorders").hide();
$(".button_order").click(function(){
$(".myorders").show();
$(".mysupplier").hide();
});
$(".button_supplier").click(function(){
$(".myorders").hide();
$(".mysupplier").show();
});
});
</script>
but if you would like to dynamicly fetch current data from db by pressing button i recommend use htmx (htmx.org)

How can I assign the var to the innerHTML of individual buttons when the buttons are created through a for loop?

Using Django, my buttons are created using a for loop and assigned values based on model values.
Based on which button is click, I want to update the "new_note_header" with the innerHTML of the button.
I have created the following JavaScript, which works but only when the first button clicked.
<script>
function ProjectSelect () {
var x = document.querySelector('button').innerHTML;
document.getElementById('new_note_header').innerHTML = x;
}
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').onclick = ProjectSelect;
});
</script>
<div class = project_container>
{% for project in projects %}
<button class = individual_project_container>
{{ project }}
</button>
{% endfor %}
</div>
<div class = note_header_container>
<div class = new_note_header, id = new_note_header>
New Note
</div>
</div>
I would be grateful for any help in adapting the JavaScript so it works for all buttons clicked.
querySelector will take the FIRST element that satisfies the selector
You could use querySelectorAll and assign a click event handler to each, but I recommend using delegation:
document.addEventListener('DOMContentLoaded', function() {
const nnHead = document.getElementById('new_note_header');
document.getElementById("project_container").addEventListener("click", e => {
const tgt = e.target.closest("button");
if (!tgt.matches(".individual_project_container")) return; // not a button
nnHead.textContent = tgt.textContent.trim();
});
});
<div class="project_container" id="project_container">
<button class="individual_project_container">Project 1</button>
<button class="individual_project_container">Project 2</button>
<button class="individual_project_container">Project 3</button>
</div>
<div class="note_header_container">
<div class="new_note_header" id="new_note_header">
New Note
</div>
</div>

How can I remove the parent div of a looped element?

Im trying to remove the parent div of a text, that is looped for every flash.
I tried getting the Element by Id but it only deletes the first flashed text.
This is the code:
{% for message in get_flashed_messages() %}
<div class="todolistitems">
<b id="todoitem">{{ message }}</b>
<button onClick="testremove()" id="deletetodo"><i class="material-icons">done</i></button>
<br>
</div>
<script>
var msg = document.getElementById("todoitem")
function testremove() {
msg.parentNode.remove();
}
</script>
{% endfor %}
Here's a way to handle this.
First, don't use the same ID more than once. But, there's no need to use them at all here. We can listen to document for a click event and then test to see if it's a delete button. If so, remove the element associated with that button. How to find that element? Easiest to group them together inside a div container and then use the ever-handy .closest(parentSelector) method. When we listen for the delete click, we need to consider that depending on where in that button the user clicks, the target of the event will either be the button or the icon within
window.addEventListener('DOMContentLoaded', () => {
document.addEventListener('click', e => {
if (['material-icons', 'btn-delete'].some(c => e.target.classList.contains(c))) {
let targ = e.target.closest('.todo-item')
console.log(targ)
targ.parentNode.removeChild(targ)
}
})
})
<div class="todolistitems">
<div class='todo-item'>
<b class='msg'>todo1</b>
<button class='btn-delete'><i class="material-icons">done</i></button>
</div>
<div class='todo-item'>
<b class='msg'>todo2</b>
<button class='btn-delete'><i class="material-icons">done</i></button>
</div>
<div class='todo-item'>
<b class='msg'>todo3</b>
<button class='btn-delete'><i class="material-icons">done</i></button>
</div>
</div>

Load data from flask into html when pressing a button

I am trying to load a variable into a HTML page when pressing a button. The problem is that I already have a function to load the initial page, and the new data shall be loaded on the same page, without redirecting.
This is the code i have by now:
.py file:
#app.route('/')
def index():
return render_template('index.html')
def get_documents():
documents = {'asd': 'as', 'def':'de'}
return render_template('index.html', documents=json.dumps(documents))
index.html file
<div>
<button onclick="Start()" id="StartButton" >Start</button>
</div>
<div id = "feed" style="display: none;">
</div>
<script>
var d = JSON.parse('{{documents | tojson | safe}}');
document.getElementById('feed').innerHTML = d.asd;
</script>
.js file:
function Start()
{
var feed_div = document.getElementById("feed");
feed_div.style.display = "block";
}
I would like that when i press the Start button, the content in the documents structure would appear in the .feed section. How could i do this?
Also, documents will be a list, but here i used a json because i wanted to try some examples i've found.
You can create div element inside the feed element, this element will contain all of your document data and will be hidden
<div id="document" style="display: hidden">
{% for item in documents %}
<div>{{ item }}</div>
{% endfor %}
</div>
and then in javascript change the display of the document element:
function start() {
document.getElementById("document").style.display = "block";
}

Form HTML, GET method. URL with multiple keywords

I'm building a search page that allows doing a search from 1-4 keywords that through the get method sends to the results page.(eg. for those keywords: one, two tree --> website.com/search/q=one+two+tree)
Right now when I add more keywords and press search it sends to the URL using just the keyword in the text input.
I tried to create a string joining the keywords with the "+" but sitll doesn't work. The following code is what I have tried.
This is a django webapp and in the form.py there is one charfield with an id tag named "add_keyword".
The function that doesn't work is send_keywords()
<body>
<link rel="stylesheet" href="style.css">
<script type="text/javascript">
var keywords_array = []
function getInputValue() {
if (keywords_array.length<4){
var ul = document.getElementById("keywords");
var li = document.createElement("li");
var inputVal = document.querySelector("#add_keyword").value;
li.appendChild(document.createTextNode(inputVal));
ul.appendChild(li);
keywords_array.push(inputVal);
}
if (keywords_array.length==4){
console.log("You've added the max number of keywords")
}
}
function send_keywords() {
query = keywords_array.join("+")
window.location.href= window.location.href+"/search/q="+query
return query
}
</script>
<h1>Dulcis in Fundo</h1>
<h2>Let's coock something, what do you have left?</h2>
{% block content %}
<form class="" action="/search/" method="GET">
<ul id="keywords">
</ul>
{{ form }}
<button type="button" onclick="getInputValue();" name="button">add</button>
<button type="submit" onclick="send_keywords()">Search</button>
</form>
{% endblock %}
</body>

Categories

Resources