Change like status with jQuery on a flask app - javascript

I am working on a flask web app and I am trying to implement the like comment feature with jQuery so that the page does not have to reload when the like button is clicked. Below are my codes. Any help will be much appreciated.
route:
#main.route('/like-comment/<int:id>', methods=["GEt", "POST"])
def like_comment(id):
comment = Comment.query.filter_by(id=id).first()
if comment is None:
flash('This comment is invalid or has been deleted by the user')
return redirect(url_for('.home'))
current_user.like_comment(comment)
return jsonify({'result' : 'success', 'like_comment' : current_user.like_comment(comment)})
JavaScript:
$(document).ready(function() {
$('.like').on('click', function () {
var comment_id = $(this).attr('comment_id');
req = $.ajax({
url : '/like-comment',
type : 'POST',
data : {
like_comment : current_user.like_comment(comment),
id : comment_id
}
});
req.done(function (data) {
$('#like'+comment.id).text(data.like_comment);
});
});
});
HTML:
{% if not current_user.is_liking_comment(comment) %}
<button class="like btn btn-pill btn-warning btn-xs" comment_id="{{ comment.id }}">
<span class="icon icon-thumbs-up" id="like{{ comment.id }}"></span> Like
</button>
{% else %}

I don't use flask, but I see you're using an attribute "comment_id", is that a Flask thing? Otherwise, you should use "data-"...
In your HTML...
<button class="like btn btn-pill btn-warning btn-xs" data-comment_id="{{ comment.id }}">
And then in jQuery...
var comment_id = $(this).data('comment_id');
But I think the problem is that your returning JSON and you haven't indicated that to your $.ajax call...
$(document).ready(function() {
$('.like').on('click', function(event) {
event.preventDefault();
var comment_id = $(this).attr('comment_id');
$.ajax({
url : '/like-comment',
type : 'POST',
data : {
like_comment : current_user.like_comment(comment),
id : comment_id
},
dataType='json'
})
.done(function (data) {
$('#like'+comment.id).text(data.like_comment);
});
});
});
Or if you don't want to use Promises...
$(document).ready(function() {
$('.like').on('click', function(event) {
event.preventDefault();
var comment_id = $(this).attr('comment_id');
$.ajax({
url : '/like-comment',
type : 'POST',
data : {
like_comment : current_user.like_comment(comment),
id : comment_id
},
dataType='json',
success: function(data) {
$('#like'+comment.id).text(data.like_comment);
}
});
});
});
Let me know if it helps...

Try adding an action to your data object to call the function on the server. See below:
data: {
action: like_comment, //or the name of your function on the server
like_comment: current_user.like_comment(comment),
id: comment_id,
},

Related

Django + Ajax: why does it redirect to a new URL and renders the response on browser?

Based on my understanding, ajax could be used to prevent the page from reloading/refreshing/redirecting after submitting a request to the server. However, my code will redirect to display the JSON response. I used e.preventDefault() and it didn't work. Is there anything that I am doing wrong?
My Django code looks like this:
views.py:
def projects(request):
if request.method == 'POST':
task_id = request.POST.get('task_id')
myUser = User.objects.get(pk=request.user.id)
myTask = Task.objects.get(pk = task_id)
myTask.claimed.add(myUser) #add the user to the task
return JsonResponse({'status': 'ok'})
projects = Project.objects.all()
tasks = Task.objects.all()
open_tasks = tasks.filter(status='Created')
proj_dict = {}
context = {
'projects' : projects,
'tasks' : tasks,
'open_tasks' : open_tasks,
}
return render(request, 'projects/projects.html', context)
My HTML:
<form action="{% url 'projects:' %}" method="POST" class='join-form' id='{{task.id}}'>
{% csrf_token %}
<input type="hidden" name="task_id" value={{task.id}}>
<button type="submit" class=" claim-font claim-button">
Join
</button>
</form>
Tha ajax call:
<script>
$(document).ready(function () {
$('#join-form').on('submit', function (e) {
e.preventDefault();
e.stopPropagation();
const url = $(this).attr('action');
console.log("here we are");
const task_id = $(this).attr('id');
$.ajax({
type: 'POST',
dataType: "json",
headers: { 'X-CSRFToken': csrftoken },
url: url,
data: {
csrfmiddlewaretoken: '{{ csrf_token }}',
task_id: task_id,
},
success: function (response) {
alert(data);
console.log("here we are");
},
error: function (response) {
console.log('error', response);
alert("shit")
}
})
return false;
});
});
</script>
Seems like ajax will make sure that my browser doesn't redirect/reload/refresh after the submit button is clicked, and only the server-side changes. However, my browser turns out to be displaying: {"status": "ok"}
Any insights are greatly appreciated!
I noticed that you have class attribute for your form. Change your JQuery selector from $('#join-form') to $('.join-form') for class attributes
<script>
$(document).ready(function () {
$('.join-form').submit(function(e) {
e.preventDefault();
// write your code here
});
});
</script>
You need to change button type from "submit" to "button"

Ajax delete with laravel 500 internal error

Hi there I am new on coding so forgive me if I am asking too much, I have this problem here this is my HTML code on blade laravel:
<button type="button" id="removecollaborator" value="{{$bank_id}}" class="btn btn-flat btn-default btn-sm delete-colaboration-button"
title="#lang('buttons.remove_option')">
<i class="material-icons">delete</i>
</button>
and here I have my ajax js:
<script type="text/javascript">
$(document).on("click", "button[id=removecollaborator]", function (data) {
var result = confirm("Are you sure you want to delete this collaborator?");
if (result) {
var bankid = $(this).val();
$.ajax({
method: "POST",
url: "{{ url('/banks/delete-bank-collaborators') }}",
data: {
_token: "{{ csrf_token() }}",
bank_id: bankid
},
success: function () {
$("button[id=removecollaborator][value=" + bankid + "]").parent().parent().parent().parent().fadeOut('slow');
},
error: function () {
console.log("error");
}
});
}
});
</script>
And here I have the controller:
public function deleteCollaborator(){
if(request()->ajax()) {
$bank_id = request()->input('bank_id');
$bank_invites = BankInvite::select('id')->where('bank_id', $bank_id)->get()->toArray();
BankInvitedUser::whereIn('bank_invites_id', $bank_invites)->delete();
return response()->json(Lang::get('general.bank_deleted'));
}
It does not work I do not know why it returns Failed to load resource: the server responded with a status of 500 (Internal Server Error). so it is the success but I think in the controller I have the problem can someone help me, please..?
try replacing
deleteCollaborator(){
with
deleteCollaborator(Request $request){
also is your route a Route::post()?

refresh data in view after ajax request symfony

I'am new in Ajax and I intregated one ajax request. The purpose is one user can like, unlike an article. Look my code :
controller
public function likeAction(Request $request, Article $article, $slug)
{
if (!$this->get('security.authorization_checker')->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
throw $this->createAccessDeniedException();
}
if ($request->isXmlHttpRequest()) {
$tokenStorage = $this->get('security.token_storage');
$currentUser = $tokenStorage->getToken()->getUser();
$likes = $article->getLikes();
foreach ($likes->getUsers() as $user) {
if ($user == $currentUser) {
throw new \Exception('Vous aimez déjà cet article !');
}
}
$likes->addUser($currentUser);
$likes->setCount($likes->getCount() + 1);
$em = $this->getDoctrine()->getManager();
$em->persist($article);
$em->flush();
$count = $article->getLikes()->getCount();
return new JsonResponse(array('data' => $count));
}
return $this->redirectToRoute('pm_platform_view', array('slug' => $slug));
}
route
pm_platform_like:
path: /like/{slug}
defaults:
_controller: PMPlatformBundle:Article:like
view
<a class="btn btn-blue-grey" id="like" role="button"></a>
<span class="counter" id="counter">{{ article.likes.count }}</span>
<script>
$( document ).ready(function() {
$(document).on('click', '#like', function (e) {
$this = $(this);
$.ajax({
type: 'GET',
url: '{{ path('pm_platform_like', {slug: article.slug}) }}',
dataType: 'JSON',
data: {},
success: function() {
//refresh article.count here
}
});
});
});
</script>
Currently the ajax request works and the "like" is persisted in database. But in my view nothing change, I have to "refresh" data, more precisly the like count attribute of article entity after the success of the ajax request. I need help for that.
Assuming you have another ajax request that gets like count.
success: function(response) {
//Recall function here that gets like count.
fnGetLikeCount();
}
Edited:
Can you post that function/ajax request that gets like count?
Edit 2:
Yes you can send response from controller and can assign/set that count in like lable/div or what ever you are using.
Your AJAX request is already send total counts in response. So, all you need to update "counter" div with total like count.
objResponse holds response of ajax request and total like count would be stored inobjResponse.data .
success: function(objResponse) { // "objResponse" is response os ajax request
$("#counter").html(objResponse.data);
^^
}
Full Code
<a class="btn btn-blue-grey" id="like" role="button"></a>
<span class="counter" id="counter">{{ article.likes.count }}</span>
<script>
$( document ).ready(function() {
$(document).on('click', '#like', function (e) {
$this = $(this);
$.ajax({
type: 'GET',
url: '{{ path('pm_platform_like', {slug: article.slug}) }}',
dataType: 'JSON',
data: {},
success: function(objResponse) { // "objResponse" is response os ajax request
//refresh article.countcounter here
$("#counter").html(objResponse.data);
^^
}
});
});
});
</script>
Read more about ajax

Like/Dislike with jQuery AJAX returns 500 (Internal Server Error) but works when I reload the page

I have a Like Status button that sends data using AJAX to the controller.
When I click the button, the button changes from "like" to "dislike" and all the classes and form action get changed as well.
The problem is, if I like the status, I see the changes reflected, but if I decided to dislike it without reloading the page, I get this error
GET http://localhost/socialnet/public/likestatusCount/undefined 500 (Internal Server Error)
If I reload the page and click dislike, my vote gets removed from the database and the button changes back to "like"
It works if I reload the page.
If I remove the get() request to retrieves the likes count, nothing happens and console.log() returns an empty row, I don't see any data being returned.
I opened laravel.log and I saw this error
local.ERROR: exception 'ErrorException' with message 'Trying to get property of non-object' in C:\xampp\htdocs\socialnet\app\Http\Controllers\FeedController.php:140
which is this line in getlikesCounter() method
return Response::json(['count' => StatusLikes::where('status_id', $status->id)->count()]);
I am using Laravel 5.2
The form in the view
#if(\App\StatusLikes::where(['status_id' => $status->id, 'user_id' => Auth::user()->id])->first())
{!! Form::open(['action' => 'FeedController#dislikeStatus', 'id' => 'dislike_form', 'class' => 'dislikeform']) !!}
<button type="submit" class="btn btn-danger btn-xs dislike" data-user="{{ Auth::user()->id }}" data-status="{{ $status->id }}" id="dislike-status">
<i class="fa fa-thumbs-down"></i> <span class="dislike-button-text">Dislike</span> <span class="dislike-button-counter">({{ $likes_count }})</span>
</button>
{!! Form::close() !!}
#else
{!! Form::open(['action' => 'FeedController#likeStatus', 'id' => 'like_form', 'class' => 'likeform']) !!}
<button type="submit" class="btn btn-info btn-xs like" data-user="{{ Auth::user()->id }}" data-status="{{ $status->id }}" id="like-status">
<i class="fa fa-thumbs-up"></i> <span class="like-button-text">Like</span> <span class="like-button-counter">({{ $likes_count }})</span>
</button>
{!! Form::close() !!}
#endif
The methods in the controller for like, dislike, and get likes count
public function likeStatus() {
if (Input::has('like_status')) {
$status = Input::get('like_status');
$selectedStatus = Status::find($status);
$selectedStatus->likes()->create([
'user_id' => Auth::user()->id,
'status_id' => $status
]);
$response = [
'status' => 'success',
'msg' => 'You have liked this status',
];
return Response::json($response);
//return redirect(route('feed'));
}
}
public function dislikeStatus() {
if (Input::has('dislike_status')) {
$status = Input::get('dislike_status');
$selectedStatus = Status::find($status);
$selectedStatus->likes()->where('user_id', Auth::user()->id)->delete([
'status_id' => $status
]);
$response = array(
'status' => 'success',
'msg' => 'You have disliked this status',
);
return Response::json($response);
//return redirect(route('feed'));
}
}
public function getlikesCounter($id) {
$status = Status::find($id);
return Response::json(['count' => StatusLikes::where('status_id', $status->id)->count()]);
}
The javascript form likeform and dislikeform
$('.likeform').submit(function(e) {
e.preventDefault();
var submitBtn = $(this).find('.like');
var form = $(this).find('.likeform')
var likeText = $(this).find('span.like-button-text');
var likeCounter = $(this).find('span.like-button-counter');
var status_id = submitBtn.data('status');
var user_id = submitBtn.data('user');
var token = $('input[name=_token]').val();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': token
}
});
$.ajax({
url: 'http://localhost/socialnet/public/likeStatus',
method: 'POST',
cache: false,
data: { like_status: status_id, user_id: user_id, _token: token },
success: function(data) {
submitBtn.removeClass('btn-info').addClass('btn-danger');
submitBtn.find($(".fa")).removeClass('fa-thumbs-up').addClass('fa-thumbs-down');
submitBtn.closest("form").removeClass('likeform').addClass('dislikeform').attr('id', 'dislike_form').attr('action', 'http://localhost/socialnet/public/dislikeStatus');
submitBtn.closest("form").find("input[name=like_status]").attr('name', 'dislike_status');
submitBtn.removeClass('like').addClass('dislike');
submitBtn.find($(".like-button-text")).removeClass('like-button-text').addClass('dislike-button-text');
submitBtn.find($(".like-button-counter")).removeClass('like-button-counter').addClass('dislike-button-counter');
likeText.text('Dislike');
$.get("http://localhost/socialnet/public/likestatusCount/" + status_id, function(data) {
likeCounter.text('(' + data.count + ')');
});
console.log(data);
},
error: function() {
console.log('error');
}
});
});
$('.dislikeform').submit(function(e) {
e.preventDefault();
var submitBtn = $(this).find('.dislike');
var form = $(this).find('.dislikeform')
var likeText = $(this).find('span.dislike-button-text');
var likeCounter = $(this).find('span.dislike-button-counter');
var status_id = submitBtn.data('status');
var user_id = submitBtn.data('user');
var token = $('input[name=_token]').val();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': token
}
});
$.ajax({
url: 'http://localhost/socialnet/public/dislikeStatus',
method: 'POST',
cache: false,
data: { dislike_status: status_id, user_id: user_id, _token: token },
success: function(data) {
submitBtn.removeClass('btn-danger').addClass('btn-info');
submitBtn.find($(".fa")).removeClass('fa-thumbs-down').addClass('fa-thumbs-up');
submitBtn.closest("form").removeClass('dislikeform').addClass('likeform').attr('id', 'like_form').attr('action', 'http://localhost/socialnet/public/likeStatus');
submitBtn.closest("form").find("input[name=dislike_status]").attr('name', 'like_status');
submitBtn.removeClass('dislike').addClass('like');
submitBtn.find($(".dislike-button-text")).removeClass('dislike-button-text').addClass('like-button-text');
submitBtn.find($(".dislike-button-counter")).removeClass('dislike-button-counter').addClass('like-button-counter');
likeText.text('Like');
$.get("http://localhost/socialnet/public/likestatusCount/" + status_id, function(data) {
likeCounter.text('(' + data.count + ')');
});
console.log(data);
},
error: function() {
console.log('error');
}
});
});
GET http://localhost/socialnet/public/likestatusCount/undefined 500 (Internal Server Error)
Means :
status_id is undefined
Because, you have :
$.get("http://localhost/socialnet/public/likestatusCount/" + status_id//..
Indeed , you have status_id got from :
var status_id = submitBtn.data('status');
And you have submitBtn is got from :
var submitBtn = $(this).find('.dislike');
However, you change the CSS class of submitBtn when there is an action (like/dislike)
Thus ,
.dislike is bad selector here, you need a selector that match the button either it is like or dislike
Assign value to submitBtn & update status_id just before calling your ajax.
$.get("http://localhost/socialnet/public/likestatusCount/" + status_id//..

Ajax search - Laravel

I am trying to create a live search using jquery, ajax and laravel. I also use pjax on the same page, this might be an issue?. Quite simply it should query the database and filter through results as they type.
When using Ajax type:POST I am getting 500 errors in my console. I get zero errors using GET but instead of returning in #foreach it will a full page view (this might be because of pjax).
Where am I going wrong?
Route:
Route::post('retailers/{search}', array(
'as' => 'search-retailers', 'uses' => 'RetailersController#search'));
Controller:
public function search($keyword) {
if(isset($keyword)) {
$data = array('store_listings' => RetailersListings::search($keyword));
return $data;
} else {
return "no results";
}
}
Model:
public static function search($keyword)
{
$finder = DB::table('retailers_listings')
->Where('city', 'LIKE', "%{$keyword}%")
->orWhere('country', 'LIKE', "{$keyword}")
->orderBy('country', 'asc')
->get();
return $finder;
}
View (store.blade.php):
<div id="flash"></div> //loading
<div id="live"> // hide content
<div id="searchword"><span class="searchword"></span></div> //search word
<table class="table">
<tbody>
#foreach($store_listings as $store)
<tr>
<td></td> //echo out all fields eg: {{ $store->name }}
</tr>
#endforeach
</tbody>
</table>
</div>
Form:
<form method="get" action="">
<input type="text" class="search-retailers" id="search" name="search">
</form>
Ajax and JS:
$(function() {
$("#search").keyup(function() {
var keyword = $("#search").val();
var dataString = 'keyword='+ keyword;
if(keyword=='') {
} else {
$.ajax({
type: "GET",
url: "{{ URL::route('search-retailers') }}",
data: dataString,
cache: false,
beforeSend: function(html)
{
document.getElementById("live").innerHTML = '';
$("#flash").show();
$("#keyword").show();
$(".keyword").html(keyword);
$("#flash").html('Loading Results');
},
success: function(html)
{
$("#live").show();
$("#live").append(html);
$("#flash").hide();
}
});
} return false;
});
});
Additional, Here is my controller for pjax, It is important to note I am using the view store.blade.php foreach in for the search and for this store listing.
public function stores($city)
{
$this->layout->header = $city;
$content = View::make('retailers.stores', with(new RetailersService())->RetailersData())
->with('header', $this->layout->header)
->with('store_listings', RetailersListings::stores($city));
if (Request::header('X-PJAX')) {
return $content;
} else {
$this->layout->content = $content;
}
}
Your route is Route::post('retailers/{search}', [...]) and there you go. You pass data to your ajax-call. In GET you get something like url?key=value but using POST the data are added to the request body not to the url.
Knowing this your route is no longer valid since it only looks up for retailers/{search} and not for retailers only (which is the url POST is using).
Well maybe it could help somebody.
As a first problem you are defining the route as POST and then in the ajax request the type GET so it would not work
Also when making POST request Laravel has the csrf check so in order to work, provide it. The js function will be like
$(function() {
$("#search").keyup(function() {
var keyword = $("#search").val();
if(keyword=='') {
} else {
$.ajax({
type: "post",
url: "{{ URL::route('search-retailers') }}",
data: {
'keyword': keywork,
'_token': '{{ csrf_token() }}';
},
dataType: 'html',
cache: false,
beforeSend: function(html)
{
document.getElementById("live").innerHTML = '';
$("#flash").show();
$("#keyword").show();
$(".keyword").html(keyword);
$("#flash").html('Loading Results');
},
success: function(html)
{
$("#live").show();
$("#live").append(html);
$("#flash").hide();
}
});
} return false;
});
});
And you can test your PHP search method doing separate tests for it.

Categories