Reducing Duplicate Javascript Code for Ajax Request - javascript

I'm writing this question because I have an AJAX request for deleting posts into my website that is working fine but I have duplicated it multiple times to match the URL for different Custom Post Type that I have in the page.
Here the original code:
jQuery(".delete-listing-btn").on("click", function(e) {
var thisPost = jQuery(e.target).parents(".agent-dashboard-listing-card")
jQuery.ajax({
beforeSend: (xhr) => {
xhr.setRequestHeader('X-WP-Nonce', msSiteData.nonce);
},
url: 'https://mallorca-select.com/wp-json/wp/v2/properties-for-sale/' + thisPost.data('id'),
type: 'DELETE',
success: function () {
alert(" Listing Deleted Successfully! ");
},
error: function (request, error) {
console.log(arguments);
alert(" Can't do because: " + error);
}
});
});
In these functions the only thing that changes is a part of the URL request like this:
'https://example.com/wp-json/wp/v2/post-type-1/' + thisPost.data('id')
'https://example.com/wp-json/wp/v2/post-type-2/' + thisPost.data('id')
'https://example.com/wp-json/wp/v2/post-type-3/' + thisPost.data('id')
'https://example.com/wp-json/wp/v2/post-type-4/' + thisPost.data('id')
I'm wondering if there is a method for detecting the post type of the post where the delete button is clicked and inject inside the URL request so I don't have to duplicate it 4 times only to change the custom post type inside the url.

Move the common AJAX code to a separate function and pass the specific URL you need in each case.
jQuery(".delete-listing-btn").on("click", function(e) {
var thisPost = jQuery(e.target).parents(".agent-dashboard-listing-card")
sendRequest('properties-for-sale');
});
const sendRequest = (requestUrl) => {
jQuery.ajax({
beforeSend: (xhr) => {
xhr.setRequestHeader('X-WP-Nonce', msSiteData.nonce);
},
url: `https://mallorca-select.com/wp-json/wp/v2/${requestUrl}/${thisPost.data('id')}`,
type: 'DELETE',
success: function () {
alert(" Listing Deleted Successfully! ");
},
error: function (request, error) {
console.log(arguments);
alert(" Can't do because: " + error);
}
});
};

To do what you require you can use another data attribute to hold the post type URL route - as you already are for the id:
jQuery($ => {
$(".delete-listing-btn").on("click", e => {
let $button = $(e.target);
let $thisPost = $button.parents(".agent-dashboard-listing-card");
let url = `https://example.com/wp-json/wp/v2/${$button.data('post-type')}/${$button.data('id')}`;
console.log(url);
// your AJAX request here...
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<button class="delete-listing-btn" data-post-type="post-type-1" data-id="1">Post Type 1</button>
<button class="delete-listing-btn" data-post-type="post-type-2" data-id="2">Post Type 2</button>
<button class="delete-listing-btn" data-post-type="post-type-3" data-id="3">Post Type 3</button>
<button class="delete-listing-btn" data-post-type="post-type-4" data-id="4">Post Type 4</button>

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.

how to test submitted data in Cypres

I need to check if some values in submitted data have expected values. To do this i tried to access and sent data by XMLHttpRequest in Cypress during the request run.
describe('test submitted data', () => {
it('some data is changed', () => {
submitBtn().click({force: true});
//in this case Cypress doesnt get into this debugger point
cy.server({
onAnyRequesty: (props) => {
debugger
}
});
//in this one Cypress go into and stops at the point but
//the data variable doesnt contrain submitedData
cy.route('PUT', `${APP_CONTEXT}/api/model/${modelId}`, (data) => {
debugger;
});
});
});
Data is sent by the way below:
$.ajax({
url: url,
method: "PUT",
data: "{"inputData":"123"}",
contentType: "application/json",
success: () => {},
error: () => {}
});
What am i doing wrong? Thanks
One more thing: and how to make Cypress check if the data condition is met? for example:
it('some data is changed', () => {
submitBtn().click({force: true});
cy.route('PUT', `${APP_CONTEXT}/api/model/${modelId}`, (data) => {
const parsedData = JSON.parse(data);
// the test is passed if the value is equal
expect(parsedData.inputData).to.eq('123');
});
UPDATE
i tried proposed answer from #richard-matsen and different callBack keys but neither were working:
onResponse
onAnyResponse
onRequest
onAnyRequest
But callback function in neither of them didnt run
it("Signature removed from the field and empty value submitted", () => {
cy.server();
submitBtn().click();
//here i check the put url as an url submitting to
cy.log(`${BASE_URL}/api/data/${formId}/${modelId}`);
cy.route({
method: "PUT",
url: `${BASE_URL}/api/data/${formId}/${modelId}`,
onAnyRequest: (data) => {
const signValue = JSON.parse(data)[`${modelId}|sign_2||`];
debugger;
cy.log(signValue);
expect(signValue).to.eq(null)
}
})
})
UPDATE UPDATE
#richard-matsen ,thanks, you were right, I did an error in method options, but I decided to simplify the route options but still the debugger cannot get in neither handler:
it("Submitted data", () => {
cy.server({ whitelist: (xhr) => console.log('custome log: server', xhr) });
submitBtn().click({force: true});
cy.route({
url: /.+/,
onResponse: (data) => {
debugger;
cy.log('onResponse signature value - ' + data);
},
onAnyResponse: (data) => {
debugger;
cy.log('onAnyResponse signature value - ' + data);
},
onRequest: (data) => {
debugger;
cy.log('onRequest signature value - ' + data);
},
onAnyRequest: (data) => {
debugger;
cy.log('onAnyRequest signature value - ' + data);
}
})
})
Also tried to click submission btn right after cy.route, but that wasn't working as well.
I appreciate your help!
The patterns for using cy.route() are
cy.route(url)
cy.route(url, response)
cy.route(method, url)
cy.route(method, url, response)
cy.route(callbackFn)
cy.route(options)
Looks like your command is interpreted as #4, but response is the value used to stub. Never seen it with a function, so is best guess.
To be sure, use the pattern with options and put function in onResponse
cy.route({
method: 'PUT',
url: `${APP_CONTEXT}/api/model/${modelId}`,
onResponse: (data) => {
expect(parsedData.inputData).to.eq('123');
}
})
Also onAnyRequesty: (props) => change to onAnyRequest: (props) =>.
In your latest code,
onAnyRequest: (data) => {,
data is already parsed so JSON.parse(data) causes an error.
In my test, I get a weird error about cross-origin when trying to re-parse within onResponse() (Expecting a message like 'Unexpected token o in JSON at position 1').
In any case, put the debugger up one line to avoid other code problems.
If cy.route() is not matching the url, you can see all calls with (temporary)
cy.server({ whitelist: (xhr) => console.log('server', xhr) }).
Maybe APP_CONTEXT !== BASE_URL?
Submit can be a native event which won't be captured by Cypress.
I think you can test if this is so, see Submit a POST form in Cypress and navigate to the resulting page.
If you do the following instead of submitBtn().click({force: true}) and the cy.route() does pick it up, then you have a native event.
cy.visit({
url: `${BASE_URL}/api/data/${formId}/${modelId}`,
method: "PUT",
form: true,
body: {
inputData :"123"
}
});

How to send js variable to Spring controller?

I have this html code
<button onclick="var pdata = $('textarea').froalaEditor('html.get');">Submit article</button>
So I want to send this pdata variable to controller. How do I do this? Or should I use a form?
If you already use jQuery, consider the jQuery.post() method.
$.post("controller/path", pdata)
.done(function(response) {
comsole.log("Response: " + response);
});
You could move this code to a function, for example, like this:
<button onclick="submitArticle()">Submit article</button>
and in JS:
function submitArticle() {
var pdata = $('textarea').froalaEditor('html.get');
$.post("controller/path", pdata).done(function(response) {
comsole.log("Response: " + response);
});
}
Note that according to jQuery docs your pdata should be
A plain object or string that is sent to the server with the request.
$("#button").click(function(){
$.ajax({
type : "POST",
url :"url",
data : {id: $("#field").val()},
timeout : 100000,
success : function(response) {
alert(response);
},
error : function(e) {
console.log("ERROR: ", e);
display(e);},
done : function(e) {
console.log("DONE");
}
});
Hey here is working example of post action ajax+jquery
consider one textfield and one button for example
MyButton
see following ajax call:
function updatData() {
var value= $("#sample").val();
$.ajax({
type : "POST",
url :"url",
data : {id:value},
timeout : 100000,
success : function(response) {
alert(response);
},
error : function(e) {
console.log("ERROR: ", e);
display(e);},
done : function(e) {
console.log("DONE");
}
});
}

Laravel ajax delete request

so here is my delete button
<button class="btn btn-danger btn-xs btn-delete delete" value="{{$post->id}}">Delete</button>
then the ajax request
<script type="text/javascript">
$(document).ready(function(){
$('.delete').click(function(){
var id = $(this).val();
alert(id);
$.ajax({
type: "DELETE",
url: "{{route('delete_post')}}",
data: { id: 1 },
success: function (data) {
console.log(data);
$("#task" + id).remove();
},
error: function (data) {
console.log('Error:', data);
}
});
});
});
</script>
the route
Route::get('delete_post','PostController#getDeletePost');
then the controller:
public function getDeletePost($post_id)
{
$post = Post::where('id', $post_id)->first();
$post->delete();
return redirect()->route('dashboard')->with(['message' => 'Successfully deleted!']);
}
so please help me identfy why nothing really happens when i press the delete button
I have modified you javascript, first issue in your code is,you must either use get request or post request, second issue you are not using named route in order call url for ajax like {{ route() }} , it should be {{ url('path') }} or name your route..
<script type="text/javascript">
$(document).ready(function(){
$('.delete').click(function(){
var id = $(this).val();
alert(id);
$.ajax({
type: "get",
url: "{{ url('/') }}",
data: { id: 1 },
success: function (data) {
console.log(data);
$("#task" + id).remove();
},
error: function (data) {
console.log('Error:', data);
}
});
});
});
</script>
You are sending a DELETE request type in your Ajax call, which would require a _method parameter with a value of DELETE added to your AJAX data. Your route is a GET route, so that is why you are seeing no action
Another problem is in your blade syntax you are referencing a named route 'delete_post', but that is your URL, not the route name. You have not named the route from what you have posted
Try updating this line in your routes file and that should allow the request to make it to your controller method.
Route::post('delete_post','PostController#getDeletePost')->name('delete_post');
Now you have to change your Ajax request type to
type: "POST"

ajax request not sending any data ASP.NET MVC project with jQuery

I'm fairly new to asp.net MVC but am baffled as to why my request isn't working.
I'm trying to send an ajax request with jquery as per:
jQuery(function ($) {
var total = 0,
share = $('div.share'),
googlePlusUrl = "https://plusone.google.com/_/+1/fastbutton?url=http://bookboon.com" + $(location).attr('pathname');
setTimeout(function() {
$.ajax({
type: 'GET',
data: "smelly",
traditional: true,
url: share.data('proxy'),
success: function(junk) {
//var $junk = junk.match(regex);
console.log(junk);
},
error: function (xhr, errorText) {
console.log('Error ' + xhr.responseType);
},
});
}, 4000);
And set a line in my RouteConfig as:
routes.MapRoute(null, "services/{site}/proxy", new { controller = "Recommendations", action = "Proxy" });
The markup has a data-attribute value as:
<div class="share" data-proxy="#Url.Action("Proxy", "Recommendations")">
And my Proxy action method starts with:
public ActionResult Proxy(string junk)
The problem is that the junk parameter is always null. I can see in the debug output that the route seems to correctly redirect to this method when the page loads (as per jQuery's document ready function), but I cannot seem to send any data.
I tried sending simple data ("smelly") but I don't receive that neither.
Any suggestions appreciated!
The model binder will be looking for a parameter in the request called junk, however you're sending only a plain string. Try this:
$.ajax({
type: 'GET',
data: { junk: "smelly" }, // <- note the object here
traditional: true,
url: share.data('proxy'),
success: function(junk) {
//var $junk = junk.match(regex);
console.log(junk);
},
error: function (xhr, errorText) {
console.log('Error ' + xhr.responseType);
},
});

Categories

Resources