How apply ajax function on specific div? - html

In a simple forum app, I have a topic page which contains multiple posts. On each post there is Like widget divs like this:
<ul>
<li>
<p id="plike_count{{post.id}}"> {{ post.likes }}</p>
</li>
<li>
{% if user.is_authenticated %}
<span data-type=" post" title="Like"> {% csrf_token %}
<i class="thumbs-up" id="likep" name="{{ post.id}}"> </i>
{% endif %}
</li>
</ul>
And here is the ajax Like snippet that is supposed to capcher each Like and update the like counts:
$(function(){
$('#likep').click(function(){
$.ajax({
type: "POST",
url: "/forum/post/like/",
data: {
'post_id': $(this).attr('name'),
'csrfmiddlewaretoken': '{{csrf_token}}'
},
success: plikeSuccess,
dataType: 'html'
});
});
});
function plikeSuccess(data, textStatus, jqXHR)
{
$('#plike_count').html(data);
}
A very similar ajax code works fine when there is only one post/div to work with but I don't know how to generalize the code for multiple posts.
So the problem is how make an id corresponding to plike_count{{post.id}} in ajax?
I've tried $('#plike_count'.conc(post_id)).html(data); instead of $('#plike_count').html(data); but it did not work.

Use
$(function(){
$('#likep').click(function(){
var _self = this;
$.ajax({
type: "POST",
url: "/forum/post/like/",
data: {
'post_id': $(this).attr('name'),
'csrfmiddlewaretoken': '{{csrf_token}}'
},
success: function (data, textStatus, jqXHR)
{
$("#plike_count"+$(_self).attr('name')).html(data);
},
dataType: 'html'
});
});
});

You're looking for the wonders of the + operator, which concatenates strings:
"a" + b

The trick is to use the context from the original click event in your ajax callback.
We do this by creating a variable within the click handler which binds the context. Also note that we use the fact that all the jQuery ajax methods return a promise object.
Instead of passing a named function to the success option we instead call the .done method on the promise. Many would say that creating a named function in the global namespace for a jQuery callback is a huge antipattern.
Note that we also use a bit more structured html so that we treat the likes as a reusable module of code.
$('.like').on('click', function(e){
var $btn = $(this);
var promise = $.post({
url: $btn.attr('href'),
data: {
id: $btn.data('id'),
csrfmiddlewaretoken: '{{csrf_token}}'
},
dataType: 'html'
});
promise.done(function(jqXHR){
$btn.parents('.like-module')
.find('.like-counter')
.html(jqXHR.responseText());
});
e.preventDefault(); // prevent following link.
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="post">
<aside class="like-module">
<div class="like-counter">0</div>
<a href="/forum/post/like/" class="like" data-id="{{ post.id }}">like</div>
</aside>
</div>
<!-- more posts --!>
Added.
Also I belive a more RESTful design would be:
POST /forum/posts/:id/likes # to like a post
DELETE /forum/posts/:id/likes # to unlike a post
POST /forum/post/likes smells like a procedure and not something which acts on a resource.

Related

Laravel 5.4: Submit a HTML form and receive a JSON response

Question: how can I communicate JSON back from a controller to my html page, and embed the response in my page, instead of destroying the page?
The long story is like this:
Embedded in a quite large html page (created by a view when I open my base URL, say, http://.../home) I have a html form. It has some data fields, and the usual "Submit" button.
<form class="form-horizontal" method="POST" action="{{ route('form.user') }}">
{{ csrf_field() }}
... lots of input fields ...
<div class="form-group">
<button type="submit" class="btn btn-primary">
Submit
</button>
</div>
</form>
The receiving route ...
Route::post('form/user','ItemController#save')->name('form.user');
And the controller ...
public function save(Request $request) {
...
return response()->json(['status' => 'Saved successfully']);
}
The whole thing works like intended, if I fill the form and hit the "Submit" button, the controller receives all input fields via the $request properties.
The problem arises after the return from the controller, the html is cleared from the browser, and the JSON is displayed.
What I need is receive the JSON and display it in a div of my original html, not replace it.
Question: what do I need to do, how can I hook into the communication to intercept and handle the JSON response, so I can display the response text in my original web page (using JQuery), and not destroy the html?
Thx, Armin.
Capture the FORM submit event, and prevent the default.
Construct an AJAX request
Dictate the response type.
Convert the form data to a serialized object to be sent to the server
Capture the returned response and apply it to a DIV.
That would look something like this:
$('form').on('submit', function(e){
e.preventDefault(); //1
var $this = $(this); //alias form reference
$.ajax({ //2
url: $this.prop('action'),
method: $this.prop('method'),
dataType: 'json', //3
data: $this.serialize() //4
}).done( function (response) {
if (response.hasOwnProperty('status')) {
$('#target-div').html(response.status); //5
}
});
});

Using Ajax in django template to update an element

So I have a button that is suppose to "Add" an "Item" to a list and update the list on the same page without refreshing it.
Adding the Item without redirecting worked. but the element is not refreshed properly
Here is my script:
<div id="list">
{% for item in items %}
{{ item.name }}
{% endfor %}
</div>
<button id="add" type="submit">+</button>
<script>
$('#add').click(function () {
$.get('/url/page/', function (data) {
$('#list').html(data);
});
});
</script>
views.py
def add_to_list(request, item_id, list_id):
item, created = List.objects.get_or_create(list_id=list_id,
item_id=item_id)
return HttpResponse(request)
I feel like I have to add something in the views? and maybe use json code?
You should append the result of your request to the div element. Try this:
$('#add').click(function () {
$.get('/url/page/', function (data) {
$('#list').append(data);
});
});
Assuming that data that you receive from GET request is not an object but just a string. If it is an object add data.name:
$('#list').append(data.name)
Hope it helps.

HTML post method vs AngularJS

I want to use AngularJS in my application, and at the initial stage I followed plain HTML for front view and for the back end potion I used a servlet and an ejb class where I organized SQL querys following CURD application method and that works really fine. Then I applied AngularJS that includes an Ajax call inside the $scope method. Once I create an Ajax method named "btnadd()", but now I cannot pass a value because the page directs to a servlet. Can any one help me to
<html ng-app="helloApp">
</head>
<body>
<div ng-controller="demoApp">
<form name="frm" method="post" action="Srvlet">
<input type="submit" name="btnadd" value="Add" ng-click="btnadd()"/>
My method in the JS file:
$scope.btnadd = function() {
$.ajax({
url: 'Srvlet',
type: "POST",
data: {
datepicker: $scope.newcontact.datepicker,
eId: $scope.newcontact.eId,
name: $scope.newcontact.name, `enter code here`
cmp: $scope.newcontact.cmp
},
success: function(data, textStatus, jqXHR) {
console.log(data);
$scope.$apply(function(){
$scope.newcontact.addRecordResult = data.addRecordResult;
});
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('Error : ' + jqXHR.responseText);
}
}); if($scope.newcontact.eId == null) {
$scope.newcontact.eId = departmentID++;
$scope.Departments.push($scope.newcontact);
} else {
for(i in $scope.Departments) {
if($scope.Departments[i].eId == $scope.newcontact.eId) {
$scope.Departments[i] = $scope.newcontact;
}
}
}
$scope.newcontact = {};
};
Hello and welcome on stackoverflow
I assume that the method btnadd() is attached to a submit button in which case it will proceed to the action. There is few possible solutions i.e. change submit button to standard button that wont send form but will call the method or/and add onsubmit="return false;" to form which will prevent form from sending
Although why don't you use an angularjs $httpinstead of jQuery?
https://docs.angularjs.org/api/ng/service/$http

Prevent Ajax.BeginForm from HTML encoding output

#using (Ajax.BeginForm("Create", "Comment",
new AjaxOptions
{
UpdateTargetId = "newComment",
OnSuccess = "function() { alert('finished " + ViewData.Model.Id + "'); }",
}))
{
...
}
outputs the following markup:
<form action="/Comment/Create" data-ajax="true" data-ajax-mode="replace"
data-ajax-success="function() { alert('finished 34'); }"
data-ajax-update="#newComment34" id="form1" method="post">
As you can see, it has HTML encoded my javascript. How do I prevent this?
EDIT: I have multiple AJAX forms on my page so the onsuccess function needs to know which one called it. In my code, you can see I am trying to pass state to this function. If OnSuccess can only take a function name (and not state), then how can I achieve this?
Personally I would use a standard Html.BeginForm helper with HTML5 data-* attributes that I will AJAXify myself:
#using (Html.BeginForm(
"Create",
"Comment",
FormMethod.Post,
new { data_id = Model.Id }
))
{
...
}
which outputs:
<form action="/Comment/Create" data-id="some id here" method="post">
...
</form>
and then in a separate javascript file I would subscribe for the .submit event:
$(function() {
$('form').submit(function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
dataId: $(this).data('id'), // <- pass the data-id HTML5 attribute
success: handleSuccess
});
return false;
});
});
function handleSuccess(result) {
$('#newComment').html(result);
// fetch the data-id of the form that trigerred the AJAX request
var id = this.dataId;
// TODO: do something with this id
}
I prefer this technique compared to the Ajax.* helpers as it gives me all the control I might need. Another advantage is that we get a clear separation between script and markup making the code nice and tidy.
Don't.
The HTML encoding is correct behavior, and the attribute value (as seen from Javascript code) will not be encoded.
I believe that It's because MVC interprets the OnSuccess (and other vars) as the name of a Javascript function and not a bit of Script.
Make a helper function that performs the script you want to act on the submit.

PHP/JQuery/AJAX, few teething problems

Morning/Afternoon guys.
Writing some JQuery AJAX shizz and getting a bit stuck. I've got the actual proccess of calling the php file done perfectly, its just trying to get the html on the page to change in a way I want it to. I want to get rid of the a with the id of the one used in the ajax call etc, and replace it with the html passed from the PHP file. Code is as follows...
$(".save_places").click(function() {
$.ajax({
url: "{/literal}{$sRootPath}{literal}system/ajax/fan_bus.php",
type: "POST",
data: ({id : this.getAttribute('id')}),
dataType: "html",
success: function(msg){
$(this).before(msg);
$(this).empty();
alert(msg);
}
});
return false;
});
And the HTML is pretty simple;
<p class="links">
<img src="{$sThemePath}images/save_places.png" alt="Save to My Places" />
<img src="{$sThemePath}images/send_friend.png" alt="Send to a Friend" />
</p>
All the stuff in the success function is experimental mashing of code, any help please?
Thanks as always.
I think what you're after is .replaceWith(), like this:
$(this).replaceWith(msg);
This replaces the <a></a> with the content coming back in msg.
Also, if you're sure the elements have IDs, you can just do this:
data: {id : this.id},
linksPara.replaceChild(newElements, oldAtag);