How can I call Ajax process to run sequentially with Dynamic action(Execute javascript code) in Oracle apex - plsql

How can I Call my Ajax process to run sequentially ? The image attached contains the Ajax processes I created. After PAYMENT_PROCESS runs, ASSIGN_PARENT_ID should run next then CONFIRM_PACKAGE runs afterward.
I used a dynamic action(which executes a javascript code) to call the Ajax PAYMENT_PROCESS as seen in my code below:
var url = "https://js.paystack.co/v1/inline.js";
$.getScript(url, function payWithPaystack() {
let handler = PaystackPop.setup({
key: 'pk_test_4c041a09529de5308f6f494058f09', // Replace with your public key
email: apex.item('P1_EMAIL').getValue(),
ref: ''+Math.floor((Math.random() * 1000000000) + 1),
onClose: function(){
alert('Window closed.');
},
callback: function(response){
let reference = response.reference;
let transid = response.trans;
apex.server.process(
'PAYMENT_PROCESS', // Process or AJAX Callback name
{
x01: reference,
x02: transid,
x03: amount
},
{
success: function (pData) { // Success Javascript
// apex.item("P1_EMP_INFO").setValue(pData);
},
dataType: "text" // Response type (here: plain text)
}
);
}
});
handler.openIframe();
});

Related

Server Side Call waits for Ajax completion - ASP Webform

After the form submission on ASP page I call this function for some background work.
$.ajax({
url: "SomeService.asmx/LoadData",
method: "POST",
data: JSON.stringify({ requestDto: { Type: "Type1" } }),
contentType: 'application/json;',
dataType: 'json',
error: function () {
alert("Error");
},
success: function (result) {
//show toast message
}
});
The service is something like this
[System.Web.Services.WebMethod(EnableSession = true)]
[System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
public async Task<SomeReponseDto> LoadData(SomeRequestDto requestDto)
{
var neededData = await GetDataFromDB();
Session[requestDto.Type"_Data"] = neededData;
return new SomeResponseDto
{
Status = true,
Message = "Data for " + requestDto.Type.ToString() + " are ready."
};
}
I want the above the work to be done in background and I need to store it in session because we can not use persistent data-base. The problem is after I submit for Type1, the service is hit and the processing will start. This will now block the UI and user can make changes. But if the User moves from Type1 to Type2 (same UI just different values for the form), it required a hit on serverside which waits for the ajax to complete. Can I make the ajax call independent to any server side calls. I am kind of new with server-side rendering so any help would be great.

ASP.NET oData patchValue received from Angular is nothing

I'm developing an app with an Angular based front-end and an ASP.NET back end using oData and Oracle. I'm at the point where I'm trying to patch records on the back end. I'm using generic boilerplate code on the back end in my controller and the patch method looks like this:
<AcceptVerbs("PATCH", "MERGE")>
Async Function Patch(<FromODataUri> ByVal key As Decimal, ByVal patchValue As Delta(Of FTP_ORDERS)) As Task(Of IHttpActionResult)
Validate(patchValue.GetEntity())
If Not ModelState.IsValid Then
Return BadRequest(ModelState)
End If
Dim fTP_ORDERS As FTP_ORDERS = Await db.FTP_ORDERS.FindAsync(key)
If IsNothing(fTP_ORDERS) Then
Return NotFound()
End If
patchValue.Patch(fTP_ORDERS)
Try
Await db.SaveChangesAsync()
Catch ex As DbUpdateConcurrencyException
If Not (FTP_ORDERSExists(key)) Then
Return NotFound()
Else
Throw
End If
End Try
Return Updated(fTP_ORDERS)
End Function
On the Angular side, I'm using $resource based service to send the update. The code that calls the resource looks like this:
(new FTPOrderService({
"key": vm.ID,
"data": vm
}, vm))
.$patch()
.then(function (data) {
alert("Order Saved!");
},
function (error) {
debugger;
}
);
The service is defined with:
.factory('FTPOrderService', function ($resource) {
var odataUrl = '../odata/FTP_ORDERS';
var results = $resource('', {}, {
'patch': {
method: 'PATCH',
params: {
key: '#key',
},
url: odataUrl + '(:key)'
}
});
return results;
})
I've also tried:
(new FTPOrderService({
"key": vm.ID,
}, vm))
.$patch(vm)
.then(function (data) {
alert("Order Saved!");
},
function (error) {
debugger;
}
);
and get the same results.
I believe that I have configured angular to send the data properly with:
.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.patch = {
'Content-Type': 'application/json;charset=utf-8'
};
}])
The debugger shows that I'm calling the URL with the appropriate key appended to it in parens and the request payload looks like this:
{key: "1239990990", data: {loading: false, selectedRow: {}, lineItems: [,…], orderId: "1239990990",…}}
data: {loading: false, selectedRow: {}, lineItems: [,…], orderId: "1239990990",…}
key: "1239990990"
Any idea of what I'm missing? There are numerous examples out there using direct calls to $http.post and a few for .patch, but nothing current using $resource.
I am not entirely sure what the cause of this issue was, but in tracing it, I did discover that intermittently an object was not being received by the patch method in .NET. The object I'm passing in is particularly heavy and what I was passing by default was actually heavier than what the ASP.NET side of the app requires. Adding code prior to the patch call to assemble an object that meets the requirements at a minimum level resolved the issue.

Working with Meteor and Async balanced-payments functions

I'm using balanced-payments and their version 1.1 of balanced.js within Meteor.
I'm trying to create a new customer using
balanced.marketplace.customers.create(formData);
Here is my CheckFormSubmitEvents.js file
Template.CheckFormSubmit.events({
'submit form': function (e, tmpl) {
e.preventDefault();
var recurringStatus = $(e.target).find('[name=is_recurring]').is(':checked');
var checkForm = {
name: $(e.target).find('[name=name]').val(),
account_number: $(e.target).find('[name=account_number]').val(),
routing_number: $(e.target).find('[name=routing_number]').val(),
recurring: { is_recurring: recurringStatus },
created_at: new Date
}
checkForm._id = Donations.insert(checkForm);
Meteor.call("balancedCardCreate", checkForm, function(error, result) {
console.log(result);
// Successful tokenization
if(result.status_code === 201 && result.href) {
// Send to your backend
jQuery.post(responseTarget, {
uri: result.href
}, function(r) {
// Check your backend result
if(r.status === 201) {
// Your successful logic here from backend
} else {
// Your failure logic here from backend
}
});
} else {
// Failed to tokenize, your error logic here
}
// Debuging, just displays the tokenization result in a pretty div
$('#response .panel-body pre').html(JSON.stringify(result, false, 4));
$('#response').slideDown(300);
});
}
});
Here is my Methods.js file
var wrappedDelayedFunction = Async.wrap(balanced.marketplace.customers.create);
Meteor.methods({
balancedCardCreate: function (formData) {
console.log(formData);
var response = wrappedDelayedFunction(formData);
console.log(response);
return response;
}
});
I get nothing back when I submit the form, except that on the server console I do see the log of the form data.
I'm sure I'm not calling some of these async functions correctly. The hard part for me here is that the balanced function are async, but I don't know if they fit into the same mold as some of the examples I've seen.
I've tried to follow this example code.
http://meteorhacks.com/improved-async-utilities-in-meteor-npm.html
Is there a specific change that needs to be done in regard to working with balanced here? Does anyone have any tips for working with Async functions or see something specific about my code that I've done wrong?
Thanks
The NPM utilities Async.wrap does the same thing as the undocumented Meteor function Meteor._wrapAsync, in that it takes an asynchronous function with the last argument function(err, result) {} and turns it into a synchronous function which takes the same arguments, but either returns a result or throws an error instead of using the callback. The function yields in a Fiber until the asynchronous callback returns, so that other code in the event loop can run.
One pitfall with this is that you need to make sure that the function you wrap is called with the correct context. So if balanced.marketplace.customers.create is a prototype method that expects this to be set to something, it will not be set properly unless you bind it yourself, using function.bind or any of the other various library polyfills.
For more information, see https://stackoverflow.com/a/21542356/586086.
What I ended up doing was using a future. This works great, I just need to do better at catching errors. Which will be a question for a pro I think ; - )
Credit should go to user3374348 for answering another similar question of mine, which solved both of these.
https://stackoverflow.com/a/23777507/582309
var Future = Npm.require("fibers/future");
function extractFromPromise(promise) {
var fut = new Future();
promise.then(function (result) {
fut["return"](result);
}, function (error) {
fut["throw"](error);
});
return fut.wait();
}
Meteor.methods({
createCustomer: function (data) {
balanced.configure(Meteor.settings.balancedPaymentsAPI);
var customerData = extractFromPromise(balanced.marketplace.customers.create({
'name': data.fname + " " + data.lname,
"address": {
"city": data.city,
"state": data.region,
"line1": data.address_line1,
"line2": data.address_line2,
"postal_code": data.postal_code,
},
'email': data.email_address,
'phone': data.phone_number
}));
var card = extractFromPromise(balanced.marketplace.cards.create({
'number': data.card_number,
'expiration_year': data.expiry_year,
'expiration_month': data.expiry_month,
'cvv': data.cvv
}));
var associate = extractFromPromise(card.associate_to_customer(customerData.href).debit({
"amount": data.total_amount*100,
"appears_on_statement_as": "Trash Mountain" }));
});
As Andrew mentioned, you need to set the context for the method.
Here's the way you can do that with Async.wrap
Async.wrap(balanced.marketplace.customers, "create");

AJAX promise without Ember Data

I have decided to not use ember-data as it's not production ready and still changing. My app only needs to make a few ajax requests anyway so it shouldn't make too big of a difference. I am having trouble understanding how to handle an ajax promise response.
When my user loads the app they already have an authenticated session. I am trying to ping the server for that users info and display it in my template. It seems my template is rendered before my ajax request returns results and then does not update with the promise.
// route
App.ApplicationRoute = Ember.Route.extend({
setupController: function(){
this.set("currentUser", App.User.getCurrentUser());
}
});
// model
App.User = Ember.Object.extend({
email_address: '',
name_first: '',
name_last: '',
name_full: function() {
return this.get('name_first') + ' ' + this.get('name_last');
}.property('name_first', 'name_last')
});
App.User.reopenClass({
getCurrentUser: function() {
return $.ajax({
url: "/api/get_current_user",
type: "POST",
data: JSON.stringify({})
}).then(function(response) {
return response;
});
}
});
In my template:
<h1> Hey, {{App.currentUser.name_first}}</h1>
How would I update the template when I receive a response or delay rendering until I have a response?
Actually the answer is quite easy: You do not need to use a promise. Instead just return an empty object. Your code could look like this:
App.User.reopenClass({
getCurrentUser: function() {
var user = App.User.create({}); //create an empty object
$.ajax({
url: "/api/get_current_user",
type: "POST",
data: JSON.stringify({})
}).then(function(response) {
user.setProperties(response); //fill the object with your JSON response
});
return user;
}
});
What is happening here?
You create an empty object.
You make an asynchronous call to your API...
... and in your success callback you fill your empty object.
You return your user object.
Note: What is really happening? The flow mentioned above is not the sequence in which those actions are happening. In reality the points 1,2 and 4 are performed first. Then some time later, when the response returns from your server, 3 is executed. So the real flow of actions is: 1 -> 2 -> 4 -> 3.
So the general rule is to always return an object that enables Ember to do its logic. No values will be displayed first in your case and once your object is filled Ember will start do its magic and auto update your templates. No hard work needs to be done on your side!
Going beyond the initial question: How would one do this with an array?
Following this general rule, you would return an empty array. Here a little example, which assumes, that you might like to get all users from your backend:
App.User.reopenClass({
getAllUsers: function() {
var users = []; //create an empty array
$.ajax({
url: "/api/get_users",
}).then(function(response) {
response.forEach(function(user){
var model = App.User.create(user);
users.addObject(model); //fill your array step by step
});
});
return users;
}
});
I'd use Ember.Deferred instead of returning an empty array as mentioned before.
App.User.reopenClass({
getAllUsers: function() {
var dfd = Ember.Deferred.create();
var users = [];
$.ajax({
url: "/api/get_users",
}).then(function(response) {
response.forEach(function(user){
var model = App.User.create(user);
users.addObject(model);
});
dfd.resolve(users);
});
return dfd;
}
});
In your model hook all you have to do is this
model: function(){
return App.User.getAllUsers();
}
Ember is smart enought and knows how to handle the promise you return, once it's resolved the model will be correctly set, you can also return a jQuery promise but it will give you some weird behavior.
You can as well set the current user as the model for your ApplicationRoute like so:
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return App.User.getCurrentUser();
}
});
Since getCurrentUser() returns a promise, the transition will suspend until the promise either fulfills or rejects.
This is handy because by the time transition is finished your model is initialized and you will see it rendered in the template.
You can read up more about async routing in Ember guides.

Issue binding JSONP data with Knockout.js

I am working on a web project that involves a cross-domain call, and I decided to use Knockout.js and ASP.NET Web Api. I used the Single Page Application template in VS 2012, and implemented the Knockout class as it is. The page works great when I make JSON call from the same domain, but when I try using JSONP from the remote server the knockout does not seem to bind the data. I can see the JSON data received from the remote while making JSONP call, but knockout cannot bind the data.
Here is my JavaScript ViewModel classes:
window.storyApp.storyListViewModel = (function (ko, datacontext) {
//Data
var self = this;
self.storyLists = ko.observableArray();
self.selectedStory = ko.observable();
self.error = ko.observable();
//Operations
//Load initial state from the server, convert it to Story instances, then populate self
datacontext.getStoryLists(storyLists, error); // load update stories
self.selectStory = function (s) {
selectedStory(s); $("#showStoryItem").click(); window.scrollTo(0, 0);
storyItem = s;
}
//append id to the hash for navigating to anchor tag
self.backToStory = function () {
window.location.hash = storyItem.id;
}
self.loadStories = function () {
datacontext.getStoryLists(storyLists, error); // load update stories
}
return {
storyLists: self.storyLists,
error: self.error,
selectStory: self.selectStory
};
})(ko, storyApp.datacontext);
// Initiate the Knockout bindings
ko.applyBindings(window.storyApp.storyListViewModel);
And my DataContext class as below:
window.storyApp = window.storyApp || {};
window.storyApp.datacontext = (function (ko) {
var datacontext = {
getStoryLists: getStoryLists
};
return datacontext;
function getStoryLists(storyListsObservable, errorObservable) {
return ajaxRequest("get", storyListUrl())
.done(getSucceeded)
.fail(getFailed);
function getSucceeded(data) {
var mappedStoryLists = $.map(data, function (list) { return new createStoryList(list); });
storyListsObservable(mappedStoryLists);
}
function getFailed() {
errorObservable("Error retrieving stories lists.");
}
function createStoryList(data) {
return new datacontext.StoryList(data); // TodoList is injected by model.js
}
}
// Private
function clearErrorMessage(entity) {
entity.ErrorMessage(null);
}
function ajaxRequest(type, url, data) { // Ajax helper
var options = {
dataType: "JSONP",
contentType: "application/json",
cache: false,
type: type,
data: ko.toJSON(data)
};
return $.ajax(url, options);
}
// routes
function storyListUrl(id) {
return "http://secure.regis.edu/insite_webapi/api/story/" + (id || "");
}
})(ko);
This page: http://insite.regis.edu/insite/index.html makes the cross-domain call to secure.regis.edu, and it is not working. However the same page on secure.regis.eduinsite/index.html making JSON call works just fine.
What am I doing wrong? Any help will be greatly appreciated.
Thanks for those provided help.
I manage to solve the issue by adding WebApiContrib.Formatting.Jsonp class to my WebApi project as explained in https://github.com/WebApiContrib/WebApiContrib.Formatting.Jsonp, and making a slight modification to my jQuery Ajax helper class as below:
function ajaxRequest(type, url, data, callbackWrapper) { // Ajax helper
var options = {
dataType: "jsonp",
crossDomain : true,
type: type,
jsonp: "callback",
jsonpCallback: callbackWrapper,
data: ko.toJSON(data)
};
return $.ajax(url, options);
}
Everything worked as a charm.
I suggest the following:
Create a simplified example (without Knockout) that just makes the AJAX call with simple, alert-style success and error callbacks. Affirm that it is throwing an error in the cross-domain case.
Check the following link: parsererror after jQuery.ajax request with jsonp content type. If that doesn't tell you enough, search the Web (and StackOverflow) for information on jQuery JSONP parserrors and callbacks.
If you're still stuck, and you've done #1 and seen what I expect you will see, re-write this post with your simplified example, and remove any references to Knockout (in title, tags). I know Knockout, but I don't know JSONP, and the folks who know JSONP don't seem to be touching this, so I think this question is reaching the wrong audience. Changing the title and tags to emphasize the JSONP/cross-domain aspect may get you the help you need.

Resources