I have the filepicker.io dialog coming up fine but on the success call back I seem to lose my 'this' context.
So my code is like this
var fileProcess ={
saveFileInfo: function () {
.....process info here
},
selectFile: function () {
filepicker.pick({ mimetype: 'image/*' }, function (Blob) {
this.saveFileInfo();
});
}
}
So is there something like "context: this" like I can do in an ajax call?
Try creating a new variable named self or me set to the current value of this OUTSIDE your callback. Then, you use closures, so you can access this from your callback through me or self.
Like:
this.mesg = "Hello";
var self = this;
function handler() {
alert(self.mesg);
}
later after a context switch...
handler(); // Will alert 'Hello'
EDIT: Oh nuts... Just realized that won't work... Try:
function handler() {
alert(this.msg);
}
var newHandler = handler.bind(this);
Later...
newHandler();
Function.prototype.bind() takes an object, and returns a function. Whenever the returned function is called, the object passed to bind() is used as this.
Related
I'm trying to set a model and retrieving it from OData after pressing a certain button.
The problem is when I call getModel right after setting the model, it returns undefined.
However, if I call getModel from another function (after model being stetted from other functions), it returns the desired output.
Code for reference:
onPressButton1: function(){
var vEntityURL = "/CustomerSet(ID='000')";
var sServiceUrl = "/Customers_SRV/";
var oServiceModel = new sap.ui.model.odata.ODataModel(sServiceUrl, true);
var oJsonModel = new sap.ui.model.json.JSONModel();
oServiceModel.read(vEntityURL, {
success: function(oData) {
oJsonModel.setData(oData);
}
});
this.getView().setModel(oJsonModel, "Customers");
var oCustomer = this.getView().getModel("Customers");
console.log(oCustomer.getProperty("/Name"));
}
The above returns undefined in the console.
However, it works if I press another button with the following function.
onPressButton2: function(){
var oCustomer = this.getView().getModel("Customers");
console.log(oCustomer.getProperty("/Name"));
}
This is not a sapui5 problem, it is the common behaviour of asynchronous code: you can be sure to have your data only in the success callback of the read method.
Move the last three lines of code inside the success function and you're done :-)
I'm filddling with sinonjs in SAPUI5. But there are some things I can't get my head around.
QUnit.module("Validation of Betaalwijze", {
beforeEach : function () {
this.oMainViewController = new MainViewController();
this.oViewStub = new ManagedObject();
var data = {
IBANPrimair: "123",
IBANSecundair: "456",
Betaalwijze: ""
};
var oModel = new JSONModel(data);
var fakeBetaalwijzeField = new Input();
sinon.stub(this.oViewStub, "getModel").returns(oModel);
sinon.stub(this.oViewStub, "byId").returns(fakeBetaalwijzeField);
sinon.stub(this.oMainViewController, "getView").returns(this.oViewStub);
},
afterEach : function() {
this.oMainViewController.destroy();
this.oViewStub.destroy();
this.fakeBetaalwijzeField.destroy();
}
});
QUnit.test("Should set an ValueState Error", function (assert) {
// Arrange
//All preparation here above.
// Act
this.oMainViewController._validateInput();
// Assert
//TODO
});
The getModel-stub works nicely when I use a "sap/ui/base/ManagedObject" for the oViewStub. But the byId-stub causes the message "Attempted to wrap undefined property byId as function" in that case.
When I use a "sap/ui/core/mvc/View" for the oViewStub, the getModel-stub is not found. (But this gives an error in the beforeEach also: Cannot read property 'viewData' of undefined.)
What is the right way to stub the View and it's methods getModel() and byId()?
The answer is quiete simple: sap.ui.base.ManagedObject does not have a method byId. This is a method of sap.ui.core.mvc.View. Just create a View instead of a ManagedObject in beforeEach and you should be fine.
BR
Chris
I need to pass a callback to a function whose signature is function('ui', {foo: bar, callback: callbackfn}). The function I want to pass is a When.js promise.
The best I've come up with:
var d = when.defer();
var p = when(d);
var q = p.then(function() {
return loadItem(newCatalogItem, name, fileOrUrl);
});
ConfirmationMessage.open('ui', { callback: d.resolve });
return q;
This works (using a deferred to prevent immediate execution, and then passing the resolve function as the callback), but seems a bit convoluted.
Is there a cleaner way?
I think you want to just promisify that ConfirmationMessage.open method (see also the when.js docs here and there), and then use it like a promise function, chaining then calls onto it.
For your specific example, that could be (using the portable promise constructor):
return when.promise(function(resolve) {
ConfirmationMessage.open('ui', { callback: resolve });
}).then(function(confirmResult) {
return loadItem(newCatalogItem, name, fileOrUrl);
});
I've tried to understand this post regarding this concept, however, I'm failing to get it. I have the following simple setup:
/server/test.js
Meteor.methods({
abc: function() {
var result = {};
result.foo = "Hello ";
result.bar = "World!";
return result;
}
});
/client/myapp.js
var q = Meteor.call('abc');
console.log(q);
This structure returns to the console undefined.
If I change the myapp.js file to:
Meteor.call('abc', function(err, data) {
!err ? console.log(data) : console.log(err);
}
I receive the Object in my console.
Ideally this is what I'd like to be able to do, but it doesn't work, stating in the console: Cannot read property 'greeting' of undefined
/client/myapp.js
var q = Meteor.call('abc');
Template.hello.greeting = function() {
return q.foo;
}
Any help in passing the data from the server object into the template would be greatly appreciated. I'm still learning JavaScript & Meteor.
Thanks!
From the Meteor.call documentation:
On the client, if you do not pass a callback and you are not inside a stub, call will return undefined, and you will have no way to get the return value of the method. That is because the client doesn't have fibers, so there is not actually any way it can block on the remote execution of a method.
So, you'll want to do it like this:
Meteor.call('abc', function(err, data) {
if (err)
console.log(err);
Session.set('q', data);
});
Template.hello.greeting = function() {
return Session.get('q').foo;
};
This will reactively update the template once the data is available.
This happens because Npm.require has Async behavior. That's the reason that you have to write a callback for Meteor.call.
But there is a solution, just use install(mrt add npm) and you'll get a function named Meteor.sync(//...) with this you can do both games: sync and async in your Meteor.call().
Reference: http://www.sitepoint.com/create-a-meteor-app-using-npm-module/
You can get the return value of a Meteor method for use in a template by using a reactive variable. Check out the working demonstration on Meteorpad
I went for a ghetto solution. But, it works for me, which is what matters, to me. Below is my code, which, in concept, I think, solves OP's problem.
In the client's main.js:
Meteor.setInterval(function() {
confirmLogin();
}, 5000);
This runs the confirmLogin() function every five seconds.
The confirmLogin function (in the client's main.js):
function confirmLogin() {
Meteor.call('loggedIn', function (error, result) {
Session.set("loggedIn", result);
});
}
The loggedIn method (in the server's main.js):
loggedIn: function () {
var toReturn = false;
var userDetails = Meteor.user();
if (typeof userDetails["services"] !== "undefined") {
if (typeof userDetails["services"]["facebook"] != "undefined") {
toReturn = true;
}
}
return toReturn;
},
The relevant helper:
loggedIn: function () {
return Session.get("loggedIn");
}
I'm using "express" and "cradle" in "nodejs". If I request my database I have to define a callback to handle the response. Unfortunately I have no access to res (response) in my callback function. What is the best practice for this problem? Here is my code.
var cradle = require('cradle');
var db = new cradle.Connection().database('guestbook');
app.get('/guestbook', function(req, res) {
db.view('guestbook/all', function(err, doc) {
console.log(doc);
// How can I use res in this callback
// to send the response?
});
});
You can just use res inside the inner callback.
In JavaScript the inner function "inherits" the variables of the outer function. Or more precisely, the function forms a closure, which is an expression that can have free variables. The closure binds the variables from its outer scope, which can be the scope of another function or the global scope.
You may try this.
Most important (perhaps your pitfall?) keep in mind that 'db.view' will mereley register a callback closure and continue. Do not close your request (by calling 'req.end') anywhere outside this closure. If you do, quite likely the request have been closed as the db returns. Once the http response object is closed any data written to it goes void.
var cradle = require('cradle');
var db = new cradle.Connection().database('guestbook');
app.get('/guestbook', function(req, res) {
// Register callback and continue..
db.view('guestbook/all', function(err, guests) {
// console.log('The waiting had an end.. here are the results');
guests.forEach(function(guest) {
if (guest.name) {
res.write('Guest N: ' + guest.name);
}
});
// Close http response (after this no more output is possible).
res.end('That is all!')
});
console.log('Waiting for couch to return guests..');
// res.end('That is all!'); // DO NOT DO THIS!!!
});
With this snippet you really should have access to res here. You should be able to use res.render() or res.send() because the db callback is wrapped in the closure of the app.get callback function.