Like System with AJAX and Laravel - ajax

I'm trying to get it so people can like a post on a button click which will upload a row to the likes table and then if they press the button again it will delete the record and unlike the post. The problem i am having is that i have rehashed a tutorial which included a boolean for a like and dislike, i do not have the boolean and have tried to reconfigure the code to accommodate that. The problem i'm having is that after i've sorted out the unauthorized errors the button now appears to be dead and doesn't do anything. I presume this mean that their is an issue with the laravel code for this. Can anyone see why the button isnt responding and point me in the direction of how i like(post) to database, check for a like and delete if the button is pressed and the row exists?
Here is what i have so far:
Table:
likes: id, post_id, user_id, timestamps()
HTML:
<a class="btn btn-not-liked like">Liked?</a>
AJAX JS:
var postId = 0;
var token = '{{ Session::token() }}';
var urlLiKes = '{{ route('likes') }}';
$('.like').on('click', function(event){
event.preventDefault();
postId = event.target.parentNode.parentNode.dataset['postid'];
var isVisit = event.target.previousElementSibling == null;
$.ajax({
method: 'POST',
url: urlLikes,
data: {isLikes: isLikes, postId: postId, _token: token}
})
.done(function() {
});
});
PHP:
$post_id = $request['postId'];
$is_visit = $request['isLike'] === 'true';
$post = Post::find($post_id);
if (!$post) {
return null;
}
$liked = Auth::user()->likes()->where('post_id', $post_id)->first();
if($liked == $is_like){
$liked->delete();
return null;
}
else{
$liked = new Like();
}
$liked->user_id = Auth::user();
$liked->post_id = $post->id;
$liked->save();
return null;
}
Please help to find the issue in this code or point me in the direction of a like system without the boolean and just a simple like(post)/unlike(delete) with Laravel and AJAX.

I think the problem is that you are performing a Boolean / Object compassion.
I suggest rewriting your if condition in:
if( !is_null($liked)){...}

Related

Retrieving a Django form field value using AJAX

For each fact in facts, there is a form where you can upvote or downvote the fact.
Further explanation is found below.
Template and Form code are listed below respectively:
template
<ul>
{% for fact in facts %}
<form method='POST' action="{% url 'facts:list' fact.pk %}" id="list_vote">
{% csrf_token %}
{{ form }}
<input type="submit" value="vote" />
</form>
{% endfor %}
</ul>
forms.py code:
VOTE_CHOICES = [
(1, 'upvote'),
(0, 'downvote')
]
class Vote(forms.Form):
vote = forms.ChoiceField(choices=VOTE_CHOICES,
widget=forms.RadioSelect(attrs={'class': 'vote'}))
For each fact in models.Fact.objects.all(), there is a form, which consists of radio buttons of 2 inputs (upvote, downvote), created for this specific fact. What I'm now doing is basically Django 101: getting the value of the fact that is being voted and update its model accordingly in the views.
What I want to do is retrieve the value of this specific fact using AJAX and update the model accordingly without leaving/refreshing the page
I think I can help you. I just went through a lot of learning on AJAX and how to connect to DJANGO templates. You'll need some javascript on your template to make the AJAX connection.
Below is a generic AJAX javascript connector function I abstracted from my recent work. It needs both prototype.js http://prototypejs.org/ and jquery.js https://jquery.com/download/ imported into your template to run. Also requires a jQuery noconflict statement to allow both to run at the same time.
Basically all you need to do is pass the AJAXconnector function I wrote your data in a {'myvariable' : 'myvalue', 'myvariable2' : 'myvalue2'} format and destination is the url (in string format) which points to your views.py processing function to handle the AJAX data and return a reply. Also its important to use a local (relative) link as your destination.
I did a little tutorial on my blog if you want to check it out too - it walks through the AJAX connection on the template (javascript side) and the server (python side) http://www.americantechnocracy.com/getArticle/4/
the code I'm posting below also has some more description at:
http://www.americantechnocracy.com/getArticle/9
Let me know if you have questions. Happy to answer.
// Requires prototype.js
// Requires jquery.js
// enable use of both prototype and jquery
var $j = jQuery.noConflict();
// get the CSRF Token
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
// function for AJAX communication of data from Template to View.py and back
function AJAXConnector(parameters, destination) {
// myParameters = {'targetPK': pk, };
myParameters = parameters;
csrfHeader = {'X-CSRFToken' : csrftoken};
// This is the start of my AJAX Function
new Ajax.Request(destination, {
method: 'post', parameters: myParameters, requestHeaders: csrfHeader,
onSuccess: function (transport) {
var response = transport.responseText || "no response text";
data = response.evalJSON();
},
onFailure: function () {
alert('Something went wrong...');
}
});
}

Updating "tr" data in laravel

I'm facing difficulty in doing this task :
- I have a table that have an add delete , update buttons for every single row I've done the add and delete thing by adding data-attribute for each button according to the row's data Id. It works perfectly for deleting and inserting elements. Yet i can't find a way to update every single row so i need help !
Note: I'm updating my elements using Ajax.
Any strategy ? i can post a screenshot for my code/view cause it is a bit too long .
More explanation : when you click on the edit button $(this) and delete button hide , and check button appears . inputs are no longer hidden for this row so the user updates the data of this row then he checks it.
The data must update inside the database .
I'm stuck nowhere because every row has its own id and its own values and only one query must be run for every row ( which is the same query for all the rows ) . It's more likely having one form for the whole table that updates only the row that must be updated .
After you click on edit button
$(document).on('click', '.btn-edit-interview', function() {
var id = $(this).attr('data-interview-id');
var selector = ('' + '.tr' + id + '');
var selectordelt = ('' + '.' + id + '');
var selectorsave = ('' + '#save-'+id + '');
$(this).hide();
$(selectordelt).hide();
$(selectorsave).show();
$(selector).prop('disabled', false);
$(selector).addClass("form-control");
$(selector).css('border: 1px solid rgb(204, 204, 204);margin-top: 16px;');
});
I just need help in finding a way do make the update query for every single row .
//HTML
<tr data-unique="{!! $yourVariable->id !!}">
<td><input value="{!! $yourVariable->value !!}"></td>
<td><button data-update="{!! $yourVariable->id !!}">Update</button></td>
</tr>
//AJAX
$('button[data-update]').click(function() {
var itemID = $(this).attr('data-update');
//Will contain value of input in that tr only
var input = $('tr[data-unique="+itemID+"] input').val();
$.ajax({
url: '/update',
type: 'POST',
dataType: 'json',
data: {item: itemID, anotherValue: input},
success:function(data){
if(data['status'] == "success"){
alert("Updated");
}
}
});
return false;
});
//Controller
public function update(Request $req){
YourModel::where('id', $req->input('item'))->update(['column' => 'value']);
return response()->json(['status' => 'success']);
}
//Route
Route::post('/update', 'YourController#update');
Hope that help

For-in Loop through Tumblr posts with ajax

The expectation is that $(".post-title").append(postTitle); will return the title of that post, as will postBody. Yet when I console.log these variables > undefined is returned.
$.ajax({
url: "http://api.tumblr.com/v2/blog/ohc-gallery.tumblr.com/posts?api_key=***",
dataType: 'jsonp',
success: function(res){
var postings = res.response.posts;
var postTitle = "";
var postBody = "";
$(".post-title").append(postTitle);
$(".post-body").append(postBody);
for (var i in postings){
postTitle = postings[i].title;
postBody = postings[i].body;
}
console.log("postBody: " + postBody);
}
});
Am I missing something basic regarding Javascript closures... I really don't know right now. I simply want to loop through created post data for later display.
Github JS code- https://github.com/mrcn/ohc/blob/master/js/tumblr.js
Github HTML code- https://github.com/mrcn/ohc/blob/master/index-posting.html#L82-L89
I got it. The problem was with how I intended to display this information on the website, and I had to alter the code accordingly. The idea was to display paired blog post titles and entries. The problem was all titles were appearing together, and all bodies were appearing together- not paired off respectively.
The updated code is more along the lines of --
Javascript --
//use $.each() or Array.forEach
$.each(postings, function (i, post) {
$(".post ").append("<h3>" + post.title + "</h3>" + post.body + "<br><br>");
});
}
});
HTML --
<div class="post-wrap"><!--post-wrap-->
<div class="post">
</div>
</div><!--post-wrap-->
The for..in is used to iterate over an object... posts is an array for you can use the normal for (var i=0;i<x;i++) loop or any other iteration methods like $.each() or Array.forEach()
$.ajax({
url: 'http://api.tumblr.com/v2/blog/ohc-gallery.tumblr.com/posts?api_key=***',
dataType: 'jsonp',
success: function (res) {
var postings = res.response.posts;
var postTitle = '';
var postBody = '';
//use $.each() or Array.forEach
$.each(postings, function (i, post) {
$(".post-title ").append(post.title);
$(".post-body ").append(post.body);
})
}
});
Not every post type supports title or body. You currently have three posts, two text and one photo. The photo post type only support photos and caption, which is causing the undefined.
Check the API for more details: https://www.tumblr.com/docs/en/api/v2

Render form with errors via AJAX

I have an action called "myAction" that render the main page of my project. This view (page), is a 2 columns layout, where in the left side have a table with all project in the database.
In the right side i render the project resume or the new project form, as the case may be.
When the user click in "New Project" button, the form is rendered via load() jQuery function. So, when the form is validate, the project is saved and your resume is rendered in the right side of the layout (removing the form), but when the form is invalid i wish render the form with errors.
All form request are sending to newAction() method controller.
The AJAX Request is:
$.ajax({
url: $form.attr('action'),
type: $form.attr('method'),
dataType: 'json',
data: $form.serialize(),
success: function(response){
var object = JSON.parse(response);
if(object.success){
$("#ProjectList").load(Routing.generate('project_my'));
fn_render_resumen(object.message);
}else{
// The form is invalid.
}
}
});
The newAction in ProjectController is:
public function newAction(Request $request){
$project = new Project();
$form = $this->createForm(new ProjectType(), $project);
if($request->isMethod('POST')){
$form->bind($request);
$response = array();
if($form->isValid()){
// Persist in the database...
$response['success'] = true;
$response['message'] = $project->getSlug();
}else{
// Here need send the form with errors to the view.
}
return new JsonResponse(json_encode($response));
}
return $this->render('aView.html.twig',Array('form' => $form->createView()));
}
So, any ideas ? Thanks !
First of all you don't need to json_encode data passed to JsonResponse; Just do this:
return new JsonResponse($response);
Try this:
if($form->isValid()){
// Persist in the database...
$response['success'] = true;
$response['message'] = $project->getSlug();
}else{
$formHtml = $this->container
->get('templating')
->render('aViewForm.html.twig',Array('form' => $form->createView()));
$response['success'] = false;
$response['form'] = $formHtml;
}
return new JsonResponse($response);
Where aViewForm.html.twig is a template that renders only your form. For example it could looks like this:
{{ form }}
And you will have complete HTML code (with errors). Something like this:
{"success":false,"form":"\u003Cform\u003E...\u003C\/form\u003E"}
and then you can process it in JS script.

Passing the signed_request along with the AJAX call to an ActionMethod decorated with CanvasAuthorize

This is a follow-up to AJAX Call Does Not Trigger Action Method When Decorated With CanvasAuthorize
So I found the following links and it seems that this is a common problem:
http://facebooksdk.codeplex.com/discussions/251878
http://facebooksdk.codeplex.com/discussions/250820
I tried to follow the advice by prabir but I couldn't get it to work...
Here's my setup:
I have the following snippet in the page where the button that triggers the whole post to facebook is located:
#if (!string.IsNullOrEmpty(Request.Params["signed_request"]))
{
<input type="hidden" id="signedReq" value="#Request.Params["signed_request"]" />
}
And then I have this snippet (inside a script tag inside the same page):
var signedRequest = $('#signedReq').val();
$('.facebookIcon').click(function () {
var thisItem = $(this).parent().parent();
var msg = thisItem.find('.compItemDescription').text();
var title = thisItem.find('.compareItemTitle').text();
var itemLink = thisItem.find('.compareItemTitle').attr('href');
var img = thisItem.find('img').first().attr('src');
postOnFacebook(msg, itemLink, img, title, signedRequest);
});
And finally, inside an external js file I have the following function:
/*Facebook post item to wall*/
function postOnFacebook(msg, itemLink, pic, itemTitle, signedReq) {
console.log(signedReq);
var siteUrl = 'http://www.localhost:2732';
$.ajax({
url: '/Facebook/PostItem',
data: {
'message': msg,
'link': siteUrl + itemLink,
'picture': siteUrl + pic,
'name' : itemTitle,
'signed_request': signedReq
},
type: 'get',
success: function(data) {
if(data.result == "success") {
alert("item was posted on facebook");
}
}
});
}
But signedReq is always undefined. And I'm not really sure I should be passing the 'signed_request' field inside the data object. Any thoughts?
Make sure you hidden input field is being populated.
Also, when you try to pull the ID of the input field via JQuery, you might not be referencing the proper element since .NET butcher's ID's of anything that's run on the server.
When I use the hidden input field trick, I set the jquery value like so:
var signedRequest = $('#<%=signedReq.ClientID %>').val();
This way, I'm getting the identifier that .NET is giving to the HTML element.
Hope that helps.
Just a guess - in your hidden field: id="signed_request" instead of id="signedReq"

Resources