Return a view from an ajax call - javascript

I have 0 experience in Ajax, and now I'm trying to get an html table to return on an ajax call.
As a result, I get the error
jquery-3.6.0.min.js:2 POST http://test.loc/%7B%7B%20url('blog/articles')%20%7D%7D 404 (Not Found)
I understand that there are still a lot of mistakes, so don't judge too much, and help in any way you can :)
Route:
Route::post('blog/articles', 'App\Http\Controllers\BlogController#articles');
Ajax on calling page:
function getBlogLists(category_id) {
var category_id = category_id;
$.ajax({
url: "{{ url('blog/articles') }}",
type: 'POST',
data: { 'category_id': category_id },
datatype: 'html',
success: function(data) {
console.log('success');
console.log(data);
document.querySelectorAll('.blog-filter__item').forEach(el => {
el.addEventListener('click', () => {
document
.querySelector('.blog-filter__item.active')
.classList.remove('active');
el.classList.add('active');
var dataFilter = $(el).attr('data-filter');
if (dataFilter == 'all') {
$('.blog-list').show();
}
else {
$('.blog-list').hide()
$(dataFilter).show()
}
});
});
},
});
}
//on page load
getBlogLists("{{ $category->id }}");
Controller:
public function articles() {
$input = Request::all();
if(Request::isMethod('post') && Request::ajax()) {
if($input['category_id']) {
$articles = Article::select('select * from blog_categories where blog_category_id = ?', array($input['category_id']));
$returnHTML = view('blog.articles')->with('articles', $articles)->render();
return response()->json( array('success', 'html'=>$returnHTML) );
}
}
}
View:
#foreach($articles as $index => $article)
<div class="blog-list category_{{ $article->blog_category_id }}">
#if ($index % 2 === 1)
<div class="blog-article blog-article--right">
<h2 class="blog-article_title">{{ $article->title }}</h2>
</div>
#else
<div class="blog-article blog-article--left">
<h2 class="blog-article_title">{{ $article->title }}</h2>
</div>
#endif
</div>
#endforeach

You have this error because you have a problem in your URL.
function getBlogLists(category_id) {
var category_id = category_id;
$.ajax({
url: "{{ url('blog/articles') }}",
Here, the url is literally {{ url('blog/articles') }}, I mean, as a string.
You are sending the request to http://test.loc/{{ url('blog/articles') }}, which once encoded gives http://test.loc/%7B%7B%20url('blog/articles')%20%7D%7D.
That's why you are getting a 404 error (not found), obviously this url doesn't exist.
First, remove the url variabilization:
function getBlogLists(category_id) {
var category_id = category_id;
$.ajax({
url: "http://test.loc/blog/articles", //or whatever your url is
Then in your controller, you just have to return the HTML and it will be inside data in your javascript success callback.
Do a simple test first:
public function articles() {
return "<h1>HelloWorld</h1>";
}
If it works with this simple "hello world", it will work with the view you are rendering as well.

Related

Call Laravel Model Function from Blade Button OnClick Javascript Function and Stay On the Page

Goal:
A user will have a list of games in a table with text boxes for each team's score. I want the user to be able to change the score of a single game, click Save (Model function updates the record), and continue saving more games while never leaving the page.
How:
After a Laravel Blade view has been rendered, I want to execute a Model function from a Javascript function on-button-click, but stay on the same page.
admin.blade.php (Javascript section in Head tag)
/* Save game from inline list on Admin page */
function inlineSaveAdmin(gameId) {
var homeScoreTxt = document.getElementById("homeScoreTxtBox");
var homeScore = homeScoreTxt.value;
var awayScoreTxt = document.getElementById("awayScoreTxtBox");
var awayScore = awayScoreTxt.value;
{{ App\Models\Game::inlineSave(gameId, homeScore, awayScore) }}
}
admin.blade.php (body of view)
<button type="button" onclick="inlineSaveAdmin({{ $game->id }});" class="btn btn-outline-success">Save</button>
So far, the Model function only executes when the page loads, not when I click the button. That is the main problem I wish to solve. Thanks for any help!
(and yes, I believe that I will need to create identical Javascript functions for each gameId that exists to be able to reference the correct homeScoreTxtBox{{ game->id }} since I don't think I could otherwise dynamically pull the text box IDs based on the Javascript function's input parameter)
1.make an ajax function on that blade file
2.call that ajax on click pass the id and updated data
3.define a route for that ajax function in web.php and
4.make a controller function on that route.
Code:
$(document).ready(function() {
$("#button").on('click', function() {
**//get id and score**
var homeScoreTxt = document.getElementById("homeScoreTxtBox");
var homeScore = homeScoreTxt.value;
var awayScoreTxt = document.getElementById("awayScoreTxtBox");
var awayScore = awayScoreTxt.value;
var game_id = gameId;
$.ajax({
type: 'POST',
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
url: '{{ route('update') }}',
//all the data you need to pass to controller function
data: {
'id': gameId,
'homescore': homeScore,
'awayscore' : awayScore
},
// dataType: 'json',
success: function(data) {
//data returned from php
// update the values
if (data) {
homeScoreTxt.value=data.homeScore,
awayScoreTxt.value=data.homeScore
}
},
fail: function() {
alert('NO');
}
});
});
});
web.php
Route::post('update', 'UpdateController#update')->name('update');
Update the values in the controller function by simple model queries.
Send updated data like this:
$response = [
'homeScore' => $homeScore,
'awayScore' => $awayScore
];
return response()->json($response);
I have followed Daniyal Ishaq's answer, and I think I'm getting closer, but I'm getting an error from the Ajax call.
Error:
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
(jquery-3.5.1.js:10099) xhr.send( options.hasContent && options.data || null );
Per Google debugger, it appears to be after/inside this call:
(jquery-3.5.1.js:9682) transport.send( requestHeaders, done );
I did some debugging, and a "status" variable is getting set to 500. Then, "isSuccess" is set to False when it gets to this line:
(jquery-3.5.1.js:9723) isSuccess = status >= 200 && status < 300 || status === 304;
That line that sets isSuccess is inside the following function, but I cannot seem to find where it's getting called from to trace where status is getting set exactly.
(jquery-3.5.1.js:9696) function done( status, nativeStatusText, responses, headers ) {
The last line I can find before the error appears is 5233:
(jquery-3.5.1.js:5233) jQuery.event.dispatch.apply( elem, arguments ) : undefined;
Shortly before that line, it is here, where event.rnamespace = undefined, and handleObj.namespace = "" (I don't know if this is relevant):
(jquery-3.5.1.js:5422) if ( !event.rnamespace || handleObj.namespace === false ||
Shortly after that, "ret" is still undefined after this line: (again, I don't know what this does, but it seems important?)
ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
handleObj.handler ).apply( matched.elem, args );
Then on 5446, it returns event.result, which is undefined.
return event.result;
That is where my debugging skills hit a dead end with jQuery. So now I ask for more help.
Ajax function in blade:
$(document).ready(function() {
#foreach($games as $game)
$("#SaveBtn{{ $game->id }}").on('click', function() {
var gameId = "{{ $game->id }}";
var saveBtn = document.getElementById("SaveBtn{{ $game->id }}");
var homeScoreTxt = document.getElementById("homeScoreTxtBox{{ $game->id }}");
var homeScore = homeScoreTxt.value;
var awayScoreTxt = document.getElementById("awayScoreTxtBox{{ $game->id }}");
var awayScore = awayScoreTxt.value;
$.ajax({
url: "{{ route('inlineSave') }}",
type: "POST",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
//all the data you need to pass to controller function
data: {
'gameId' : {{ $game-> id }},
'homeScore': homeScore,
'awayScore' : awayScore
},
dataType: "json",
traditional: true,
success: function(data) {
//data returned from php
// update the values
if (data) {
homeScoreTxt.value = data.homeScore;
awayScoreTxt.value = data.awayScore;
saveBtn.innerText = 'Resave';
alert('Success!');
}
},
error: function() {
alert('An error has occurred!');
}
});
});
#endforeach
});
Resulting HTML for Ajax function:
$(document).ready(function() {
$("#SaveBtn11870").on('click', function() {
var gameId = "11870";
var saveBtn = document.getElementById("SaveBtn11870");
var homeScoreTxt = document.getElementById("homeScoreTxtBox11870");
var homeScore = homeScoreTxt.value;
var awayScoreTxt = document.getElementById("awayScoreTxtBox11870");
var awayScore = awayScoreTxt.value;
$.ajax({
url: "http://mbcathletics/admin",
type: "POST",
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
//all the data you need to pass to controller function
data: {
'gameId' : 11870,
'homeScore': homeScore,
'awayScore' : awayScore
},
dataType: "json",
traditional: true,
success: function(data) {
//data returned from php
// update the values
if (data) {
homeScoreTxt.value = data.homeScore;
awayScoreTxt.value = data.awayScore;
saveBtn.innerText = 'Resave';
alert('Success!');
}
},
error: function() {
alert('An error has occurred!');
}
});
});
... many more of the same function for different button IDs ...
});
Button in blade: (calls its respective function successfully)
<button id="SaveBtn{{ $game->id }}" type="button" class="btn btn-outline-success">Save</button>
Route in web.php: (remember, I do not want to leave the page, I just want it to execute the Controller function... I don't know what to put in the first parameter - the URL)
Route::post('/admin', [App\Http\Controllers\HomeController::class, 'inlineSave'])->name('inlineSave');
Controller function: (it doesn't really do anything right now, I'm just trying to test connectivity before I do the heavy lifting)
public static function inlineSave()
{
$game = Game::find($gameId);
$score = $game->home_score;
$game->home_score = $score;
$response = [
'homeScore' => $homeScore,
'awayScore' => $awayScore
];
return response()->json($response);
}
Thank you! I am sorry for the detail, but it's the only I know how to help.

like and unlike with javascript and Laravel

I'm trying to implement a functionality where user can like and unlike product using javascript I followed this Laravel - Favourite / Un-Favourite button but it doesn't work for me, the button can't be clicked, any idea on how I can fix this?
Routes
Route::get('product/like/{id}', ['as' => 'product.like', 'uses' => 'LikeController#likeProduct']);
Route::get('product/{product}/unlike','LikeController#destroy')->name('product.unlike');
Javascript
<script>
function addToFavourites(productid, userid) {
var user_id = userid;
var product_id = productid;
$.ajax({
type: 'post',
url: 'product/like/{id}',
data: {
'user_id': user_id,
'product_id': product_id,
},
success: function () {
// hide add button
$('#addfavourites' + product_id).hide();
// show delete button
$('#deletefavourite' + product_id).show();
},
error: function (XMLHttpRequest) {
// handle error
}
});
}
Blade file
#if($product->isLiked)
<div id="addfavourites{{$product->id}}" onClick="addToFavourites({{$product->id}}, {{ Auth::user()->id }})"> unlike </div>
#else
<div id="deletefavourite{{$product->id}}" onClick="deleteFromFavourites({{$product->id}}, {{ Auth::user()->id }})" > like </div>
#endif
Make your routes accept a post method because you're posting through Ajax
Route::post('product/like/{id}', ['as' => 'product.like', 'uses' => 'LikeController#likeProduct']);
Route::post('product/{product}/unlike', 'LikeController#destroy')->name('product.unlike');
And use ES6 template string and add a CSRF token header to the Ajax request
function addToFavourites(productid, userid) {
// Redundant
// var user_id = userid;
// var product_id = productid;
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
method: 'post',
url: `/product/like/${productid}`, // Use ES6 template and point to the url from root /
data: {
'user_id': userid,
'product_id': productid,
},
success: function () {
// hide add button
$('#addfavourites' + productid).hide();
// show delete button
$('#deletefavourite' + productid).show();
},
error: function (XMLHttpRequest) {
// handle error
}
});
}
Hope this helps

Understanding Django/REST/JS code functionality

I have the following code in my website:
<tr onclick="editUsers(29)" data-id="29">
editUsers:
function editUsers(id) {
loadUsers(false, id, showUsers, true);
}
loadUsers:
function loadUsers(insert, id, func_call, html_form) {
var data = insert ? {insert: true} : {}
if (html_form)
data.html_form = true;
$.ajax({
type: 'GET',
url: '/rest/user/' + id + '/',
data: data
})
.done(function (data) {
func_call(data, insert, id);
})
.fail(function () {
});
}
When I click on the row, it should open an interface to edit the selected row/user, but nothing happens. I do get a reply in the console, which looks like it should work, but it doesn't. Can someone explain why it doesn't work?
The reply in question:"GET /rest/user/29/?html_form=true HTTP/1.1" 200 3170
I have the same functionality elsewhere in my code, which adds a new user:
function addUsers() {
loadUsers(true, 0, showUsers, true);
}
<div class="btn btn-primary pull-right" onclick="addUsers()">Add User</div>
The above doesn't work, editing the user doesn't either.
EDIT: showUsers function
function showUsers(data, insert, id) {
var form = $(data),
$a= form.find('select[name="a"]'),
$b= form.find('select[name="b"]');
$a.on("change", function (e) { $b.val($a.val()).trigger('change'); });
var p = {
type: BootstrapDialog.TYPE_PRIMARY,
title: '{% trans "Add User" %}',
message: form,
closable: true,
cssClass: 'usersDialog',
buttons: [
{
label: gettext('Cancel'),
hotkey: 27,
action: function (dlg) { dlg.close(); }
},
{
label: gettext('Save'),
cssClass: 'btn-primary',
action: function (dlg) {
var data = form.find('#users-form').serializeForm();
dlg.close();
var storeData = function storeData(data) {
data.html_form = true;
$.ajax({
type: data.id == '' ? 'POST' : 'PUT',
url: '/rest/user/' + (data.id == '' ? '' : data.id + '/'),
data: data,
dataType: 'json',
headers: {'X-CSRFToken': '{{ csrf_token }}'}
})
.done(function (res) {
//self.updDeviceFields(res);
if (conflictDialogs.length > 0)
storeData(conflictDialogs.pop());
else
location.reload();
//$.dreamAlert({type: 'success', message: gettext('Changes saved'), position: 'right'});
}).fail(function (jqXHR, textStatus, errorThrown) {
console.log([jqXHR.status, jqXHR, textStatus, errorThrown]);
if (jqXHR.status == 400) {
p.message = $(jqXHR.responseText);
form = p.message;
currentForm = form;
currentDialog = BootstrapDialog.show(p);
}
else if (jqXHR.status == 500) {
currentDialog = BootstrapDialog.show(p);
}
//$.dreamAlert({type: 'error', message: gettext('Error saving changes'), position: 'right'});
});
}
storeData(data);
}
}
]
}
if (conflictDialogs.length > 0) {
p.animate = false;
p.cssClass += ' flip';
}
currentDialog = BootstrapDialog.show(p);
currentForm = form;
}
I figured this out when I dug deep into the code. Turns out I had a syntax error which I completely missed when writting the code.
When copy pasting the code from a different page, I copied the variable name as well. My HTML looked like this:
<div class="row">
<div class="col-xs-6">{% render_field foo_form.one bar_style %}</div>
<div class="col-xs-6">{% render_field foo_form.two bar_style %}</div>
</div>
When it should have looked like this:
<div class="row">
<div class="col-xs-6">{% render_field foo_form.one foo_style %}</div>
<div class="col-xs-6">{% render_field foo_form.two foo_style %}</div>
</div>
I didn't see the style of importance, since it was defined as an empty list, so I completely missed the error.

Ajax function inside JavaScript is not getting called

I am trying to render the template called reset_password_page.html using AJAX. I intend to send some data to this template. The problem is that page is not getting loaded. It gets loaded when I use location.href, but this cannot be used as I won't be able to send any data to the template.
function trial() {
if ("{{ verified }}" == "yes") {
document.getElementById('lbl_verify').style.display = "block";
document.getElementById('lbl_verify2').style.display = "none";
window.setTimeout(function() {
$(document).ready(function() {
$.ajax({
url: "{% url 'reset_password_page' %}",
type: "POST",
data: {
csrfmiddlewaretoken: '{{ csrf_token }}'
},
async: false,
});
});
}, 1000);
} else {
}
}
views.py
def reset_password_page(request):
return render(request,"reset_password_page.html")
Its due to the if condition used.You are comparing
if ("{{ verified }}" == "yes")
which is false.
try if ({{ verified }} == "yes") which will fetch verified value.

Error 422 Ajax Post using Laravel

I'm trying to make a simple Ajax post using Laravel 5. I read that there is a issue with the Csrf Token matching and that i could put my uri into the VerifyCsrfToken expection to step around this. This part functions, however now I get a 422 error when i make the post.
Did I mess something up in my code? How can I get this working? Here is what I have:
HTML:
<div class = "q-form">
{!!Form::open(array('url' => 'questions')) !!}
<div class = "form-group">
{!! Form::hidden('user_id', $myid, ['class' => 'form-control']) !!}
{!!Form::label('title', 'Title:')!!}
{!!Form::text('title', null, ['class'=> 'form-control'])!!}
{!!Form::label('question', 'Question:')!!}
{!!Form::textarea('question', null, ['class'=> 'form-control area', 'placeholder' => 'What would you like to ask?'])!!}
{!!Form::submit('Ask!', ['class'=> 'btn btn-danger form-control ask'])!!}
</div>
{!! Form::close() !!}
</div>
JS:
$('.ask').click(function(e) {
e.preventDefault();
var postData = $(this).serializeArray();
var base_url = 'http://rem-edu-es.eu1.frbit.net/';
$.ajax({
type: "POST",
url: base_url + "questions",
data: postData,
success: function (data) {
console.log(data);
}
});
});
Controller:
public function book()
{
if(Request::ajax()){
return Response::json(Input::all());
}
}
VerifyCsrfToken:
class VerifyCsrfToken extends BaseVerifier
{
protected $except = [
'book/*',
'book',
'questions'
];
}
Error handling an object within response.
error :function( data ) {
if( data.status === 422 ) {
var errors = $.parseJSON(data.responseText);
$.each(errors, function (key, value) {
// console.log(key+ " " +value);
$('#response').addClass("alert alert-danger");
if($.isPlainObject(value)) {
$.each(value, function (key, value) {
console.log(key+ " " +value);
$('#response').show().append(value+"<br/>");
});
}else{
$('#response').show().append(value+"<br/>"); //this is my div with messages
}
});
}
422 is a default response when validation fails.
When you processing ajax response, you need to process "success" and "error". Example from my code:
$.ajax({
url: $(this).data('url'),
type: "post",
dataType: "json",
data: values,
success: function (data) {
$('#list').append(data.view);
},
error: function (data) {
var errors = $.parseJSON(data.responseText);
$.each(errors, function (key, value) {
$('#' + key).parent().addClass('error');
});
}
});
By the way, you can pass a _token parameter with your ajax post, then you don't need to disable CSRF protection. Just add a hidden input
{!! Form::token() !!}
in your form that you send to a server via ajax.
Try adding status code in your response:
public function book()
{
if(Request::ajax()){
return Response::json(Input::all(), 200);
}
}

Categories

Resources