My JavaScript function is not working in my html - javascript

I am trying to run a function called send mail but it doesn't run at all because the response is supposed to be 201 when it runs but django returns a 200 response like it isn't there. I tried running the function directly in my console and it worked fine so the backend is working as excpected.
Here is the JS code:
document.addEventListener('DOMContentLoaded', function() {
// Use buttons to toggle between views
document.querySelector('#inbox').addEventListener('click', () => load_mailbox('inbox'));
document.querySelector('#sent').addEventListener('click', () => load_mailbox('sent'));
document.querySelector('#archived').addEventListener('click', () => load_mailbox('archive'));
document.querySelector('#compose').addEventListener('click', compose_email);
document.querySelector('#compose-form').addEventListener('submit',send_mail);
// By default, load the inbox
load_mailbox('inbox');
});
function compose_email() {
// Show compose view and hide other views
document.querySelector('#emails-view').style.display = 'none';
document.querySelector('#compose-view').style.display = 'block';
// Clear out composition fields
document.querySelector('#compose-recipients').value = '';
document.querySelector('#compose-subject').value = '';
document.querySelector('#compose-body').value = '';
}
function load_mailbox(mailbox) {
// Show the mailbox and hide other views
document.querySelector('#emails-view').style.display = 'block';
document.querySelector('#compose-view').style.display = 'none';
// Show the mailbox name
document.querySelector('#emails-view').innerHTML = `<h3>${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}</h3>`;
fetch(`/emails/${mailbox}`)
.then(response => response.json())
.then(emails => {
// Print emails
console.log(emails);
// ... do something else with emails ...
});
}
function send_mail(){
fetch('/emails/', {
method: 'POST',
body: JSON.stringify({
recipients: document.querySelector('#compose-recipients').value,
subject: document.querySelector('#compose-subject').value,
body: document.querySelector('#compose-body').value
})
})
.then(response => response.json())
.then(result => {
// Print result
console.log(result);
});
}
Here is the HTML
{% extends "mail/layout.html" %}
{% load static %}
{% block body %}
<h2>{{ request.user.email }}</h2>
<button class="btn btn-sm btn-outline-primary" id="inbox">Inbox</button>
<button class="btn btn-sm btn-outline-primary" id="compose">Compose</button>
<button class="btn btn-sm btn-outline-primary" id="sent">Sent</button>
<button class="btn btn-sm btn-outline-primary" id="archived">Archived</button>
<a class="btn btn-sm btn-outline-primary" href="{% url 'logout' %}">Log Out</a>
<hr>
<div id="emails-view">
</div>
<div id="compose-view">
<h3>New Email</h3>
<form id="compose-form">
<div class="form-group">
From: <input disabled class="form-control" value="{{ request.user.email }}">
</div>
<div class="form-group">
To: <input id="compose-recipients" class="form-control">
</div>
<div class="form-group">
<input class="form-control" id="compose-subject" placeholder="Subject">
</div>
<textarea class="form-control" id="compose-body" placeholder="Body"></textarea>
<input type="submit" class="btn btn-primary"/>
</form>
</div>
{% endblock %}
{% block script %}
<script src="{% static 'mail/inbox.js' %}"></script>
{% endblock %}
Here the Documentation for the django API:
To send an email, you can send a POST request to the /emails route. The route requires three pieces of data to be submitted: a recipients value (a comma-separated string of all users to send an email to), a subject string, and a body string. For example, you could write JavaScript code like
fetch('/emails', {
method: 'POST',
body: JSON.stringify({
recipients: 'baz#example.com',
subject: 'Meeting time',
body: 'How about we meet tomorrow at 3pm?'
})
})
.then(response => response.json())
.then(result => {
// Print result
console.log(result);
});
If the email is sent successfully, the route will respond with a 201 status code and a JSON response of {"message": "Email sent successfully."}.

Related

How do disable redirecting when I clicking on a button? Django

I am trying to create a like button for my page. thats okey its working but when I click the button page is refreshing. When I click on the like button, I want the counter showing the number of likes to increase. I try used Ajax but I failed. here are my codes..
Views:
def liked_post(request,pk):
post =get_object_or_404(UserPosts, id=request.POST.get("userposts_id"))
liked = False
if post.like_post.filter(id = request.user.id).exists():
post.like_post.remove(request.user)
liked = False
else:
post.like_post.add(request.user)
liked = True
return HttpResponseRedirect(reverse('detail', args=[str(pk)] ))
def detail_post(request,_detail):
postDetail = UserPosts.objects.get(pk = _detail)
liked = False
if postDetail.like_post.filter(id= request.user.id).exists():
liked = True
context= {
"detail":postDetail,
"liked":liked
}
return render(request,"DetailPost.html",context)
Javascript file:
$(document).ready(function () {
//like ajax call
$('.like-form').submit(function (e) {
e.preventDefault();
const userposts_id = $('.like-btn').val();
const token = $('input[name=csrfmiddlewaretoken]').val();
const url = $(this).attr('action')
$.ajax({
method: "POST",
url: url,
headers: { 'X-CSRFToken': token },
data: {
'userposts_id': userposts_id
}
})
})
})
Template:
<form class="btn-group mt-1 like-form" action="{% url 'like_post' detail.pk %}"
method="POST">
{% csrf_token %}
{% if request.user.is_authenticated %}
{% if detail.username_id == request.user.id %}
<button class="btn btn-primary btn-sm" disabled>Like</button>
{% else %}
{% if liked %}
<button class="btn btn-danger btn-sm " type="submit" name="userposts_id"
value="{{ detail.id }}">Unlike</button>
{% else %}
<button class="btn btn-primary btn-sm like-btn"
type="submit" name="userposts_id" value="{{ detail.id }}">Like</button>
{% endif %}
{% endif %}
{% else %}
<span class="px-2 pt-1">
Login to like
</span>
{% endif %}
<span class="bg-dark px-4 pt-1 like-count text-white"> {{total_post_likes}}</span>
</form>
Does anyone have an idea?
You are redirecting to detail page in your like_post view. Instead of redirecting return JsonResponse
def liked_post(request):
if request.is_ajax():
pk = request.POST.get('userposts_id')
post = get_object_or_404(UserPosts,id=pk)
if request.user in post.like_post.all():
liked = False
post.like_post.remove(request.user)
else:
liked = True
post.liked.add(request.user)
return JsonResponse({'liked': liked, 'count': post.like_post.count()})
return redirect('detail')
this will return a json with liked and count .
<span class="bg-dark px-4 pt-1 like-count text-white"> {{total_post_likes}}</span>
Get span to render likes from js
$.ajax({
type: "GET",
url: url,
success: function (response) {
console.log(response) //response will be what you send in jsonresponse in django view
$('.like-count').innerHtml =`${response.count}`
}
})

Submitting a form through Javascript via POST method

index.js
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#compose').addEventListener('click', compose_email);
document.querySelector('#compose-form').onsubmit = send_email;
// By default, load the inbox
load_mailbox('inbox');
});
function compose_email() {
// Show compose view and hide other views
document.querySelector('#compose-view').style.display = 'block';
// Clear out composition fields
document.querySelector('#compose-recipients').value = '';
document.querySelector('#compose-subject').value = '';
document.querySelector('#compose-body').value = '';
}
function send_email()
{
const recipients = document.querySelector('#compose-recipients').value;
const subject = document.querySelector('#compose-subject').value;
const body = document.querySelector('#compose-body').value;
//console.log(recipients)
fetch('/emails', {
method: 'POST',
body: JSON.stringify({
recipients: recipients,
subject: subject,
body: body,
})
})
.then(response => response.json())
.then(result => {
// Print result
console.log(result);
});
}
inbox.html
<div id="compose-view">
<h3>New Email</h3>
<form id="compose-form">
<div class="form-group">
From: <input disabled class="form-control" value="{{ request.user.email }}">
</div>
<div class="form-group">
To: <input id="compose-recipients" class="form-control">
</div>
<div class="form-group">
<input class="form-control" id="compose-subject" placeholder="Subject">
</div>
<textarea class="form-control" id="compose-body" placeholder="Body"></textarea>
<input type="submit" class="btn btn-primary"/>
</form>
</div>
Submitting a form through Javascript via POST method but I am getting an output of GET /? HTTP/1.1" 200 1667 in terminal..
It should be 201 via POST
When I am writing the fetch function in Console.It is working fine
After submitting the form it is just returning back to the inbox page.
Since you are doing a "fetch" in your code, you should prevent the default form submission on the "submit" button click (This this the default behaviour). To achieve this you can receive the "event" as a parameter in the "send_email" function and then do a "event.preventDefault()".
function send_email(event) {
// Your code
...
// Prevent the default form submission
event.preventDefault();
}
More details # https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onsubmit

How to style each div that is created by JavaScript code

I'm creating a site for emails, where a user upon clicking a mailbox (inbox, sent, archived) I will show them all the emails that belong to said mailbox.
Now my problem is the layout, the borders of each email are not displaying the way I want. This is how it should be, where the email with gray background is a read one, while white is not:
This is what code turns up:
I want them separated but I can't get it to work. Help would be appreciated!
inbox.js:
function load_mailbox(mailbox) {
// Show the mailbox and hide other views
document.querySelector('#emails-view').style.display = 'block';
document.querySelector('#compose-view').style.display = 'none';
// Show the mailbox name
document.querySelector('#emails-view').innerHTML = `<h3>${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}</h3>`;
//get me all the emails in inbox(example)
fetch(`/emails/${mailbox}`)
.then(response => response.json())
.then(emails => {
//for each email
emails.forEach(myFunction);
function myFunction(item) {
//create a new div htmlelement
const element = document.createElement('div');
//give it a class in case i need it
element.setAttribute("class", "email-dv")
//add info to this div
element.innerHTML += item.sender + "<br>";
element.innerHTML += item.subject + "<br>";
element.innerHTML += item.timestamp + "<br>";
//create the borders for the div
//issue here, it is not creating a rectangle for each div
element.style.boder = "groove";
//if email is not read
if (item.read === false) {
element.style.backgroundColor = "white";
}
else {
element.style.backgroundColor = "grey";
}
element.addEventListener('click', function() {
console.log('This element has been clicked!')
});
//add it to the main div for all emails
document.querySelector('#emails-view').append(element);
}
});
inbox.html :
{% extends "mail/layout.html" %}
{% load static %}
{% block body %}
<h2>{{ request.user.email }}</h2>
<button class="btn btn-sm btn-outline-primary" id="inbox">Inbox</button>
<button class="btn btn-sm btn-outline-primary" id="compose">Compose</button>
<button class="btn btn-sm btn-outline-primary" id="sent">Sent</button>
<button class="btn btn-sm btn-outline-primary" id="archived">Archived</button>
<a class="btn btn-sm btn-outline-primary" href="{% url 'logout' %}">Log Out</a>
<hr>
<div id="emails-view" >
</div>
<div id="compose-view">
<h3 id="h">New Email</h3>
<form id="compose-form">
<div class="form-group">
From: <input disabled class="form-control" value="{{ request.user.email }}">
</div>
<div class="form-group">
To: <input id="compose-recipients" class="form-control">
</div>
<div class="form-group">
<input class="form-control" id="compose-subject" placeholder="Subject">
</div>
<textarea class="form-control" id="compose-body" placeholder="Body"></textarea>
<input type="submit" class="btn btn-primary" id="submit-button"/>
</form>
</div>
{% endblock %}
{% block script %}
<script src="{% static 'mail/inbox.js' %}"></script>
{% endblock %}
Well, first of all you have a typo:
element.style.boder you're missing the "r" in border. Can you check that first?

Why does my site reload after clicking edit, but before saving the changes?

So i have a pretty basic site, where you can add blog posts with a title, author and content. The posts also get two buttons - a delete and an edit button. Both buttons, and adding the posts to the html adds/deletes/edits the chosen posts in a .json file too, trough a local json server. Everything works fine except one - when i click the edit button in one of the sites it should give 2 new button to the form, and fill the form with the posts values. Except, when i click on edit, i can see for a second the two new buttons in the form is added (save and cancel) but in just a blink it also reloads the whole site, preventing me from editing the posts with the button.
Here is my html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://bootswatch.com/4/yeti/bootstrap.min.css">
<script src="https://kit.fontawesome.com/6baa217c17.js" crossorigin="anonymous"></script>
<title>Washington Post</title>
</head>
<body>
<div class="container mt-4">
<h1 class="display-4 text-center">
<i class="fas fa-book-open text-primary"></i>My<span class="text-primary">Blog</span></h1>
<form action="" id="book-form">
<div class="form-group">
<label for="title">Title</label>
<input type="text" id="title" class="form-control">
</div>
<div class="form-group">
<label for="author">Author</label>
<input type="text" id="author" class="form-control">
</div>
<div class="form-group">
<label for="content">Content</label>
<input type="text" id="content" class="form-control">
</div>
<div id="btn-container">
<button id="add-post-button" class="btn btn-primary btn-block">Add Post</button>
</div>
<!-- POSTS -->
<div class="row">
<div id="post-container" class="col">
</div>
</div>
<script src="script.js"></script>
</body>
</html>
and here is the javascript code
//Fő változók
const baseUrl = "http://localhost:3000/posts";
const postContainer = document.getElementById("post-container");
const addPostBtn = document.getElementById("add-post-button");
//input mezők
const titleInput = document.getElementById("title");
const contentInput = document.getElementById("content");
const authorInput = document.getElementById("author");
const typeInput = document.getElementById("type");
//eventlisteners
addPostBtn.addEventListener("click", addPost);
postContainer.addEventListener("click", editOrDelete);
//függvények
function loadPosts(){
fetch(baseUrl)
.then(res => res.json())
.then(json => {
json.forEach(element => {
postContainer.appendChild(generatePostElement(element));
});
});
};
function generatePostElement(object) {
let postElement = document.createElement("div");
postElement.id = `post-${object.id}`;
postElement.classList = "card mt-5";
postElement.innerHTML = `<div class="p-5">
<h1>${object.title}</h1>
<span>${object.content}</span>
<blockquote>${object.author}</blockquote>
<button class="btn btn-danger btn-sm delete" id-to-delete="${object.id}">Delete</button>
<button class="btn btn-info btn-sm edit" id-to-edit="${object.id}">Edit</button>
</div>`;
return postElement;
};
function addPost(e){
e.preventDefault();
let newPostObject = {
title: titleInput.value,
author: authorInput.value,
content: contentInput.value
};
fetch(baseUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(newPostObject)
})
.then(res => res.json())
.then(json => {
resetForm();
postContainer.appendChild(generatePostElement(json));
});
};
function editOrDelete(e){
if (e.target.hasAttribute("id-to-delete")) {
deletePost(e.target.getAttribute("id-to-delete"));
} else if (e.target.hasAttribute("id-to-edit")){
prepareEditPost(e.target.getAttribute("id-to-edit"));
} else {
console.log("egyik sem");
}
};
function deletePost(id) {
let deleteUrl = `${baseUrl}/${id}`;
fetch(deleteUrl, {
method: 'DELETE'
})
.then(res => console.log("Post " + id + " deleted"))
.then(res => {
document.getElementById(`post-${id}`).remove();
});
};
function prepareEditPost(id) {
window.scrollTo(0, 0);
document.getElementById("btn-container").innerHTML = `
<button id="edit-btn" class="btn btn-success btn-block" id-to-edit="${id}">Save</button>
<button id="reset-btn" class="btn btn-danger btn-block">Cancel</button>`;
let editBtn = document.getElementById("edit-btn");
let resetBtn = document.getElementById("reset-btn");
editBtn.addEventListener("click", editPost);
resetBtn.addEventListener("click", resetForm);
let postUrl = `${baseUrl}/${id}`;
fetch(postUrl)
.then(res => res.json())
.then(json => {
//console.log(json);
titleInput.value = json.title;
contentInput.value = json.content;
authorInput.value = json.author;
})
};
function editPost(e) {
e.preventDefault();
let editPostObject = {
title: titleInput.value,
content: contentInput.value,
author: authorInput.value,
};
let id = e.target.getAttribute("id-to-edit");
let editUrl = `${baseUrl}/${id}`;
fetch(editUrl, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(editPostObject)
})
.then(res => res.json())
.then(json => {
resetForm();
let HTMLElementTotEdit = document.getElementById(`post-${id}`);
HTMLElementTotEdit.parentNode.replaceChild(generatePostElement(json), HTMLElementTotEdit);
});
};
function resetForm() {
titleInput.value = "";
contentInput.value = "";
authorInput.value = "";
document.getElementById("btn-container").innerHTML = `<button id="add-post-button" class="btn btn-primary btn-block">Add Post</button>
`;
};
//kezdés
loadPosts();
If anyone can help me to prevent the site from reloading upon clicking the edit button that would be awesome! If anything is now clear please ask, english is not my native language.
make sure that you add submit button to the form and the other buttons without type="submit"

How to get data from AJAX request with Symfony 4?

I'm trying to get data from an AJAX request with Symfony 4 and what I get is not that I'm expecting.
Here is my routes.yaml
(...)
ajax_test:
path: /ajax/test
defaults: { _controller: 'App\Controller\AjaxTestController::test' }
requirements:
_method: POST
My controller :
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class AjaxTestController extends AbstractController
{
public function test(Request $request) {
if ($request->isXmlHttpRequest()) {
$serializer = $this->get('serializer');
$response = $serializer->serialize('test ok', 'json');
return new JsonResponse(['data' => $response]);
}
return new Response("test ko", 400);
}
}
Here is the template where I make the AJAX request :
{% extends "layout.html.twig" %}
{% set active = 'connexion' %}
{% block page_title 'Login' %}
{% block final_javascripts %}
{{ encore_entry_script_tags('sendCredentials') }}
{% endblock %}
{% block content %}
(...)
<div class="row mt-4">
<div class="col-md-6">
<form id="connexion-form" action="{{ path('security_connexion') }}" method="post">
<div class="form-group">
<label for="email">Email</label>
<input type="text" id="email" name="_email" class="form-control">
</div>
<div class="form-group">
<label for="password">Mot de passe</label>
<input type="password" id="password" name="_password" class="form-control">
</div>
<button type="submit" class="btn btn-primary button">Se connecter</button>
</form>
</div>
</div>
</div>
</div></div>
{% endblock %}
And finally the JavaScript file (sendCredentials.js) where I make AJAX request :
$(document).ready(function() {
$('#connexion-form').submit(function(event) {
sendCredentials($('#email').val(), $('#password').val());
});
});
function sendCredentials(username, password) {
$.ajax({
method: "POST",
url: "/ajax/test",
data: {username: username, password: password},
async: false
}).done(function(msg) {
console.log(msg['data']);
console.log(msg);
});
}
The first log console.log(msg['data']); displays undefined. The second log console.log(msg); displays me the html code of the template itself, that is to say the code of the template generated by twig. I don't understand why. How to get the data wanted : 'test ok' ?
P.S. : I don't use credentials yet (username and password), I'm just making tests, I want first the AJAX request to work.

Categories