xhr.post not getting JSON response - dojo

I'm trying to use Dojo to post to my server. The server is returning a JSON response (I have debugged it and know its returning a sensible value) but I'm just getting a 'Syntax error' in the Javascript console when it returns. Any ideas?
function submitStatusUpdate() {
dojo.xhr.post({
form:"statusUpdateForm",
handleAs: "json",
load: function(data){
alert('Saved with id ' + data.id);
},
error: function(err, ioArgs){
// again, ioArgs is useful, but not in simple cases
alert('An error occurred');
console.error(err); // display the error
}
});
}
I've also tried it like this
function submitStatusUpdate() {
var posted = dojo.xhr.post({
form:"statusUpdateForm",
load: function(data){
},
error: function(err, ioArgs){
// again, ioArgs is useful, but not in simple cases
console.error(err); // display the error
}
});
posted.then(function(response){
alert('returned ' + response);
});
}
But the response that gets printed out in my alert just seems to be the HTML for my entire page. I'm expecting a JSON object. I'm struggling to find a simple example that tells me how to submit a form, and then have a callback function that reads the response.
Thanks
EDIT (thanks to Richard for the guidance)
This is the working version.
<script language="Javascript">
dojo.require("dijit.form.Button");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.form.CheckBox");
function sendForm(){
var form = dojo.byId("myform");
dojo.connect(form, "onsubmit", function(event){
// Stop the submit event since we want to control form submission.
dojo.stopEvent(event);
// The parameters to pass to xhrPost, the form, how to handle it, and the callbacks.
// Note that there isn't a url passed. xhrPost will extract the url to call from the form's
//'action' attribute. You could also leave off the action attribute and set the url of the xhrPost object
// either should work.
var xhrArgs = {
form: dojo.byId("myform"),
load: function(data){
// As long as the server is correctly returning JSON responses, the alert will
// print out 'Form posted. ' and then the properties and values of the JSON object returned
alert("Form posted." + data);
},
error: function(error){
// We'll 404 in the demo, but that's okay. We don't have a 'postIt' service on the
// docs server.
alert("error");
}
}
// Call the asynchronous xhrPost
alert("Form being sent...");
var deferred = dojo.xhrPost(xhrArgs);
});
}
dojo.ready(sendForm);
</script>
This is (kind of) what my form looks like. This will work anyway (my real form is much bigger). Interestingly I had to change my normal [input type="submit"...] tag into a [button...] to get it to work properly
<form method="post" id="theform" action="postIt">
<input value="Some text" name="formInput" type="text"/>
<input name="checkboxInput" type="checkbox"/>
<button id="submitButton" type="submit">Send it!</button>
</form>

A JavaScript syntax error on parsing an XMLHttpRequest reply usually indicates invalid data from the server. My favourite tool for monitoring XMLHttpRequest traffic is Firebug. It parses JSON so if there's anything wrong, you'll know immediately.
Once you've determined that the JSON data from the server is valid, have a look at the following example from the Dojo documentation. I think it does what you're trying to do.

Related

Handling API call errors with Axios

Hi I'm using Axios to build my first API call app , the API I'm trying to get data from is the Pokemon API database pokeapi.co. The code in my app.js document to make the API call and use the data looks like this:
app.get("/", function(req, res){
res.render("home.ejs");
});
app.get("/data", async(req, res) => {
var inputSearch = req.query.searchTerm;
axios.get('https://pokeapi.co/api/v2/pokemon/' + inputSearch) //The API
.then((body) => {
var pokeData = body.data;
res.render("data.ejs", {EJSpokeData: pokeData});
})
.catch((err) => {
res.send('Data not found', err.statusCode);
})
});`
This links to a form in an ejs document that looks like this:
<form action="/data" method="GET" id="searchForm">
<input type="text" id="searchBox" placeholder="Enter Pokemon name or ID number.." name="searchTerm">
<input type="submit" value="Submit" id="submit">
</form>
The API is called when the user enters either the Pokémon's name or its ID number into the input to be passed to Axios, my system works fine and returns the data I need, however the name can't be capitalized as the name values in the central API are all lower case so capitalizing a name will cause the system to search for a value that isn't in the API and eventually time out the app giving me the error message "localhost didn’t send any data".
This will also occur if the user spells a name wrong or enters an ID number that isn't present in the API. Also, if the user leaves the input field blank a crash occurs as my ejs document tries to process data that is not present. Is there any way to launch some kind error page if the get request doesn't return any data? Is there any way to prevent the submit request being activated if the input field is blank?
I've tried to res.render an error page in the .catch section but it doesn't see to work, can anyone help?
I don't know anything about express specifically so I can't help you with how to render things, but your API questions I can help with.
If we want to call the API with a lower case name that's easy! We don't need to care about what the user types into the input because we can convert it to lower case before calling the API:
var inputSearch = req.query.searchTerm.toLowerCase();
If we want to ignore empty strings, we can use a conditional statement. There are lots of ways to check for empty strings but the easiest is to just say if (myString) {...} because an empty string will evaluate to false while all other strings are true.
if (inputSearch) {
/* ...axios... */
} else {
res.send("Empty search term");
}

Component method response object data binding

I am starting to lose my mind in debugging an application that I inherited from a fellow developer who is absent.
I have narrowed down the problem to the following place in code (php files are checked, Vue instances are initialised, there are no syntax errors).
This is my the component that gets initialised:
var RadniStol = Vue.component('radnistol', {
template: '#template-RadniStol',
data() {
return {
tableData: [],
requestData: {
sort: "ID",
order: "DESC"
}
}
},
methods: {
reloadTable: function (event) {
data = this.requestData;
this.$http.post('php/get/radni_stol.php', data).then(response => {
console.log(response.data.bodyText);
this.tableData = response.data.records;
});
},
.
.
.
The PHP file that gets called with the POST method is working correctly, querying the database and echoing the response in a JSON format.
The thing that is making me pull out my hair is the following: the console.log(response.data) outputs the following into the console:
{"records":[{"DODAN_NA_RADNI_STOL":"1","..."}]}
It is an JSON object that I expected to have but when trying to assign it to the data of the component with:
this.tableData = response.data;
or any other way… response.data.records returns ‘undefined’ in the console. I have tryed with JSON.parse() but no success.
When logging types to console:
response variable is a response object with a status 200 and body and bodyText containing the data from the database.
response.data is a string type containing the string JSON with the data from the database.
When trying to use JSON.parse(response.data) or JSON.parse() on anything in the callback of the POST method I get the following error in the console:
RadniStol.js?version=0.1.1:17 Uncaught (in promise) SyntaxError: Unexpected token in JSON at position 0
at JSON.parse (<anonymous>)
at VueComponent.$http.post.then.response (RadniStol.js?version=0.1.1:17)
at <anonymous>
I am really starting to lose my mind over this issue, please help!
Thank you
If response.data is string, with JSON inside, then to access the records field, you should decode it like this:
JSON.parse(response.data).records
Not sure this has something to do with PHP or Vue.js, it is just plain javascript issue.
If it not decodes, than problem is definitely in response.data. For example
{"records":[{"DODAN_NA_RADNI_STOL":"1","..."}]}
is not a valid JSON, because key "..." needs to have some value.
But it seems to me that response.data is already parsed.
What I suggest you to do, is to write handler of the response as separate function, make response object that mimics actual response object by hand, and then test it separately from request. So you could show us request object and function that works with it.
I had the same error and fixed it.
Result will be response.body not response.data.
Here is my code:
getS: function(page) {
this.$http.get('vue-manager?page=' + page).then((response) => {
var data = JSON.parse(response.body);
this.student = data.data.data;
this.pagination = data.pagination;
});
},

dynamic change doesn't work on vuejs input

i'm working on a vue file and have a form :
<div class="input-group">
<span class="input-group-addon">Montant</span>
<input type="number" class="form-control" v-model="amount" v-bind:value="pattern['value']"]>
</div>
my tab pattern is loaded like that :
var request = $.ajax({
url: '{{ path ('home') }}promos/pattern/'+value,
})
request.success(function(data){
if(data['pattern']==='yes'){
this.pattern=data[0];
alert(this.pattern['value']);
}
})
and my instance :
var instance = new Vue({
el: "#General",
data: {
[...]
pattern: []
}
and the request is made evertyime i do 'action a'. I have the right alert with the value i want everytime i do 'action a' but the input stays at 0 and won't dynamically change.
Something is wrong with your code. Firstly, let's look at your ajax request:
request.success(function(data){
if(data['pattern']==='yes'){
this.pattern=data[0];
alert(this.pattern['value']);
}
})
What is the form of your data response? Because you are checking something with data['pattern'], and then you are trying to associate to this.pattern something that you call data[0]
Then, as stated in #thanksd answer, you are referencing a wrong this in your ajax callback, you need to create a self variable:
var self = this
var request = $.ajax({
url: '{{ path ('home') }}promos/pattern/'+value,
})
request.success(function(data){
if(data['pattern']==='yes'){
self.pattern=data[0];
alert(this.pattern['value']);
}
})
Finally, you write:
<input type="number" class="form-control" v-model="amount" v-bind:value="pattern['value']"]>
So there are a few mistakes here. Firstly, you have a ] at the end of the line that has nothing to do here.
Secondly, you are using v-bind:value, this is not something that is going to be responsive. If you want this input to be responsive, you should use v-model and set the value of amount when you want to change the input value.
Hope this helps
Three things:
The this in your success handler is not referencing the Vue instance. You need to set a reference outside the scope of the handler and use that instead.
You can't chain a success callback to jQuery's ajax method in the first place. It's defined as a property in the parameter object passed to the call. (Maybe you copied code over wrong?)
You need to get rid of v-model="amount" if you want the input's value to reflect the value bound by v-bind:value="pattern"
Your code should look like this:
let self = this; // set a reference to the Vue instance outside the callback scope
var request = $.ajax({
url: '{{ path ('home') }}promos/pattern/'+value,
success: function(data) { // success handler should go in the parameter object
if (data['pattern']==='yes') {
self.pattern=data[0];
alert(this.pattern['value']);
}
}
})

DataTable().ajax.reload() not defined

I have the following code under DT v1.10:
var oTable = $('#items')
.dataTable({
sDom: "<'row'<'col-md-4'l><'col-md-6'f>r>t<'row'<'col-md-4'i><'col-md-7'p>>",
oLanguage: {
sLengthMenu: "_MENU_ per page"
},
ajax: "/items",
bProcessing: true,
bServerSide: true,
aoColumnDefs: [
{
aTargets: [-1],
bSearchable: false,
bSortable: false
}
]
})
.on('click', '.btn-danger', function (e) {
if (confirm('Are you sure you want to delete SKU "' + $(this).data('sku') + '"?')) {
$.getJSON($(this).attr('href'), function (data) {
if ('success' in data) {
oTable.ajax.reload(null, false);
}
});
}
event.stopPropagation();
return false;
});
When the server responds with success, it tries to call the line oTable.ajax.reload(null, false); but I always get the error Uncaught TypeError: Cannot read property 'reload' of undefined
What am I doing wrong here?
You're using old API: $().dataTable() (v1.9 and earlier) which is still available in DataTables v1.10. The old API returns jQuery object, so you should use .api() in order to use DataTable API methods:
oTable.api().ajax.reload();
The new API is returned via: $().DataTable()
Datatables FAQ
Q.: I get an error message stating that an API method is not available
A.: Very likely you are using a jQuery object rather than a DataTables API instance. The form $().dataTable() will return a jQuery object, while $().DataTable() returns a DataTables API instance. Please see the API documentation for further information.
API documentation
It is important to note the difference between $( selector ).DataTable() and $( selector ).dataTable(). The former returns a DataTables API instance, while the latter returns a jQueryJS object. An api() method is added to the jQuery object so you can easily access the API, but the jQuery object can be useful for manipulating the table node, as you would with any other jQuery instance (such as using addClass(), etc.).
As a follow up to phillip100's answer, you dont have to change all your old code, or change the initialization method just to use the new API. You can always get the dataTables 1.10.x API on the fly :
...
if ('success' in data) {
//oTable.ajax.reload(null, false);
$('#items').DataTable().ajax.reload(null, false);
}
...
Would be perfectly well too. jQuery dataTables check if there already is a dataTables instance of $("#items"), so there will be no redundancy.

jquery .live on form submit not picking up dynamically added inputs

when my ajaxupload script finishes it adds a read-only input w/ the value of the image's URL.
it is a long script, but i think this is the relevant part that fires on successful completion:
var location = '<div id="'+ID+'_location" class="img_location">' + '<input name="'+ID+'" class="location regular-text" type="text" size="50" readonly="readonly" value="'+response+'" />';
$(container).append(location).show(); //create readonly input
$(container) is defined just as the parent div of the upload button. that part seems to work... the image is uploaded, it is saved properly, and the input w/ the image's location is added to to the DOM. but i've discovered a bug that if I click my SAVE button (which triggers my ajax save function) then this new input is NOT captured.
here is my save function:
$('form#childoptions').live('submit', function(e) {
e.preventDefault();
var values = $(this).serialize();
alert(values);
var data = {
action: 'save_function',
type : 'save',
_nonce: '<?php echo $nonce; ?>',
formdata: values
};
$.post(ajaxurl, data, function(response) {
//alert(response);
if(response == 1) {
show_message(1);
t = setTimeout('fade_message()', 2000);
} else {
show_message(99);
t = setTimeout('fade_message()', 2000);
}
});
//return false;
});
only the new input is not captured. the rest works properly. there is also no problem if i refresh in between as I presume the input is part of the DOM. which is why i thought to use .live. i thought i had solved the issue twice- 1. i wasn't using a "name" on the dynamic input and 2. i wasn't using .live on the form. but now i am doing both and not getting anywhere.
all help is much appreciated. let me know if there is more information I can provide.
It appears that your using live on the whole form, not on inputs. So the live event binding would try to pickup new forms with id childoptions. This won't work. You'd be better off using bind() instead. Have you tried:
$('form#childoptions').bind('submit', function(e) {…}
I'm curious if this will fix your issue.