I'm building a shopping cart with Backbone and I'm having a hard time determining how to structure the interaction with the server. When the user hits the checkout (and after the validation) I need to:
Save the Order using order.save() - Because the order was created on the client this will hit the route on the server and give me back an ID. I need the ID before I process the order.
On success I call a custom method on the Order which hits the server again which does a request to the card processing service.
I either report the err to the client and let him modify and retry or I update the order record and create a Payment record in the database.
Here is my processOrder method in the Order Model:
processOrder: function() {
var order = this.toJSON();
$.ajax({
url: '/api/order/process',
type: 'POST',
data: order,
dataType: 'json',
success: function(res) {
console.log(res);
},
error: function(err) {
//show error message
console.log('error: ' + JSON.stringify(err));
}
});
}
This is where the form is submitted in my view
saveOrder: function() {
...
var order = this.order;
order.set(this.frmJSON);
order.save(this.frmJSON, {
success: function(res) {
console.log('order saved...');
order.processOrder();
},
error: function(err) {
console.log(JSON.stringify(err));
}
});
}
The order is saved on the server and the Order gets an ID inserted into it. When I call processOrder it works until it gets to the ajax call. It never hits the server and the browser hangs up with no error. Is there a better way to structure these steps?
Related
I am creating a registration form in AngularJS, wherein once the admin fills the form and on submit, I am doing two things: 1. Saving the data into the DB. 2. Sending an email to the person with his username and password. So on submitting my application is taking some time (around 5-7 seconds) to post the success message back on the screen. So I want to show some message while these background operations complete. I need your help as I am new to AngularJS.
createUserService.Register(obj, function(data) {
if (data.error) {
console.log("Check " + data.error);
} else {
alertify.alert("Successfully Registered");
$state.reload();
}
This is my service:
function Register(obj, callback) {
$http({
method : 'POST',
url : '/api/addUserOps',
data : obj
}).then(function(response) {
callback(response.data);
}, function(error) {
callback(error);
});
}
});
You can try this way.
Service function
function Register(obj) {
return $http({
method : 'POST',
url : '/api/addUserOps',
data : obj
});
}
Calling your function
// Trying using https://github.com/cgross/angular-busy for showing a loader here.
createUserService.Register(obj)
.then(function(data){
// stop your loader here with a success message.
})
.catch(function(error) {
// your error message here.
})
Hope you find this useful.
The below code has both success and failure handling
jQuery.ajax({
type:"post",
dataType:"json",
url: myAjax.ajaxurl,
data: {action: 'submit_data', info: info},
success: function(data) {
successmessage = 'Data was succesfully captured';
$("label#successmessage").text(successmessage);
},
error: function(data) {
successmessage = 'Error';
$("label#successmessage").text(successmessage);
},
});
$(":input").val('');
return false;
However we are not following the above...We are following as below
jQuery.ajax({
type:"post",
dataType:"json",
url: myAjax.ajaxurl,
data: {action: 'submit_data', info: info},
success: function(data) {
if(data.responseType == 'success') {
// success
}
if(data.responseType == 'failure') {
// failure
}
}
});
$(":input").val('');
return false;
Is our approach is the correct or wrong approach ??
Basically every response will be success and show error message based on the response type
Please advise. We need to follow the best practice
data. responseType doesn't return a 'success' or 'failure'. It is contains an enumerated value which represents the type of response coming back to you like text, json, arrayBuffer etc..
Hence in the second code block both if statements will be exceuted to be false and nothing will be done with the response received.
I think you should go with the first approach because
Whether you are using raw JS or a library to implement this functionality, you'll have access to the state of the request i.e. whether the request was successful; met with an error and finally whether it has been completed.
Make proper use of these events and their respective callbacks to manipulate the UI for a better user experience. For example, if the request was unsuccessful, you'd want to update the user interface to reflect that their changes weren't successful while if it was successful, you'd want to tell them so. Don't keep the user waiting!
With jQuery, you'd make use of the success and error callbacks. You also get other callbacks such as complete and beforeSend to be invoked for apporopriate use.
$.ajax({
//Other code
success: function(msg)
{
// Update the UI here to reflect that the request was successful.
doSomethingClever();
},
error: function(msg)
{
// Update the UI here to reflect that the request was unsuccessful
doSomethingMoreClever();
},
complete: function(msg)
{
// Update the UI here to reflect completion
doSomethingEvenMoreClever();
}
});
take a look at this
I'm using angularjs to create a simple SPA which allows users to interact with a Bookings list in Hosted SharePoint 2013.
I've got the HTTP GET working fine and retrieving bookings for various filtered queries.
However, now I want to Insert and Update records into the list, but Fiddler shows an 'HTTP Error 403' occurred and the following under JSON tab:
value=The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again.
I would appreciate some help confirming the following code should work. A Submit button on new booking form triggers the post:
$scope.submitForm = function () {
//new booking
if ($scope.editableBooking.Id == 0) {
service.insertBooking($scope.editableBooking, function (data) {
$scope.editableBooking = data;
});
}
// Update booking
else {
console.log("[submitForm] Update");
service.updateBooking($scope.editableBooking, function (data) {
$scope.editableBooking = data;
console.log('[updatedBooking] id = ' + $scope.editableBooking.Id)
});
}
}
Within my factory I have a service to insert booking:
var insertBooking = function (newBooking, callback) {
console.log('[insertBooking] Id = ' + newBooking.Id + " Storeno = " + newBooking.Storeno);
$http({
method: 'POST',
url: "/_api/web/lists/GetByTitle('Bookings')",
data: $.param({
Title: newBooking.Storeno,
Description: newBooking.Description,
BookedBy: newBooking.Bookedby,
StartDate: newBooking.StartDate
}),
headers: { 'Accept': 'application/json; odata=verbose' }
}).success(function (data) {
console.log("[insertBooking] POST worked");
console.log('[insertbooking] New Id = ' + data.Id);
callback(data);
}).error(function (er) {
console.log('[insertBooking] Error = ' + er);
});
}
Searching StackOverFlow is this post on Error 403 which talks about the AppManifest. I don't have access to this file - it's on a corporate intranet - and I haven't built an installable app, just angularjs files called via a CEWP.
Any suggestions please on how to update a SP list?
I've had this same error in the past
The security validation for this page is invalid and might be corrupted. Please use your web browser's Back button to try your operation again.
I found this blog by Wictor Wilén that explains how to refresh the digest token.
Basically you insert this line before your $http invocation:
UpdateFormDigest(_spPageContextInfo.webServerRelativeUrl, _spFormDigestRefreshInterval);
Some main points from the blog:
This method is synchronous, so there's no need to worry about callbacks etc.
it uses an update interval and only updates the form digest when needed – so if your digest hasn't expired, there are no additional calls to SharePoint
I am using ng-resource to do ajax request. I want to send extra info besides the data.
For example, I have an article entity on my server
exports.fetchArticle = function(req, res, next) {
var article = req.article
return res.json({data: article, message: 'success fetch article'})
}
The reason I wrap it is that, in the case of deletion, it makes no sense to send data, I can just return res.json({data: null, message: 'deleted successfully'})
on my client side, I have:
$scope.fetchArticle = function() {
Article.get({articleId: $routeParams.articleId}, function(response) {
$scope.article = response.data
$scope.ajaxSuccess = response.message
}, function(err) {
$scope.ajaxError = err.data.message
})
}
$scope.article is not an instance of ng-resource anymore, thus I can't do further request with $scope.article, i.e. this will cause error, since $scope.article is a plain json object:
$scope.article.$update(function(response) {...})
If I simply return res.json(article) from server, it works, but I can't send along the message.
The reason I dont generate the message from client but fetch from server is that, the error message is from server, I want to keep success message consistent with the error message.
Is there any other elegant way to send the message?
Assuming that all your servers responses follow this format:
{
data: {/*...*/},
message: 'some message'
}
You could use $http's transformResponse for that, so that you get an ngResource instance that is your returned object while still processing your message. For that, you need a transform-function:
function processMessage(data, message) {
//Do whatever you want with your message here, like displaying it
}
function transform(response) {
processMessage(response.data,response.message);
var data = response.data;
delete response.data;
delete response.message;
for(var attributeName in data) {
response[attributeName] = data[attributeName];
}
return response;
}
Then you can add this function to $http's default transfroms in the config of your app:
angular.module("yourApp",[/* ... */])
.config(function($httpProvider){
//....all your other config
$httpProvider.defaults.transformResponse.unshift(transform);
});
Now all repsonses from $http get transformed by this function, triggering processMessage and leaving you with a ngResource instance of the returned object.
When I save new data to a DataStore in Angular, I don't want to specify the _id. The system automatically assigns one. From looking at the network trace, the _id is passed back to the application in the response - https://baas.kinvey.com/appdata/appxxx/activities/54ac3d8671e2d7933b0116b4 - but I don't see anyway of finding that in the Angular documentation about how to retrieve that _id so I can add it to an existing list or do other processing.
var promise = $kinvey.DataStore.save('activities', {
text : $scope.newActivity.text ,
duedate : '2015-01-01'
});
promise.then(
function () {
$scope.newActivity.text = '';
},
function (error) {
//Kinvey insert finished with error
alert("Error insert: " + JSON.stringify(error));
});
Kinvey will actually return the object to you in the promise, and you can just grab the _id off the returned object.
promise.then(function(data) {
// Here's where you get your _id
$scope.newActivity.text = data._id;
}, function(err) {
console.error(err);
});