I'm trying to do something that seems like it should be incredibly simple but have been searching for hours on end with no luck. I simply want to query a subclass of Parse.Object for a given objectId (ideally using .get() but .find or .first could work too) and assign that entire object to a variable I can access outside of the query. I understand that queries return promises and I am able to log the object I want to capture from inside of my .then() function but I can't figure out how to access it elsewhere. Here's what I have right now and I think I am on the right track.
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
thisLunchQuery.equalTo("objectId", lunchIdTemp);
var thisLunch = thisLunchQuery.find().then(function(results) {
console.log(results[0]);
});
This logs the entire object I want to access and I can see it's properties in the console. However, I would like to be able to access the "thisLunch" variable elsewhere in my code. As it stands, I can't do that. I'm assuming that's because of the scope of the variable. How can I define that variable in such a way that it gets a bigger scope
Here's a more comprehensive peace of code showing what I'm trying to do
render: function() {
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
function assignLunch(results){
//not sure what goes here
}
thisLunchQuery.equalTo("objectId", lunchIdTemp);
thisLunch = thisLunchQuery.find().then(assignLunch);
var templateArgs ={
thisPlans: this.model.toJSON(),
thisLunch: thisLunch
};
$(this.el).html(this.template(templateArgs));
return this;
this.delegateEvents();
}
As you can see, I'm trying to grab the object so I can pass it in to a template and access its attributes there. I hope this helps, I'm pretty new to all of this.
UPDATE:
Here's my best attempt at trying to chain queries so that I can use part of the result from the first one as a parameter for a second one and then use both queried for objects in the final callback function.
render: function() {
var thisLunchQuery = new Parse.Query(Lunch);
var thisLocationQuery = new Parse.Query(Location);
var lunchIdTemp = this.model.get("lunchId");
function assignLunch(results){
lunchObject = results[0];
thisLocationQuery.equalTo("objectId", results[0].get("locationId");
thisLocationQuery.find.then(assignLocation);
}
function assignLocation(locationResults, lunchObject){
// I'd like to be able to access the location I just found (locationResults[0]) as
//well as the original lunchId from the first query inside this callback
var templateArgs ={
thisPlans: this.model.toJSON(),
thisLunch: lunchObject,
thisLocation: locationResults[0];
};
$(this.el).html(this.template(templateArgs));
}
thisLunchQuery.equalTo("objectId", lunchIdTemp);
thisLunch = thisLunchQuery.find().then(assignLunch);
return this;
this.delegateEvents();
}
Obviously this doesn't quiet work but I'm not sure how to pass along data like I'm trying to. Maybe I should be using .when?
What you need to do is define a function that does what you want to do with your results, and pass it to the promise success method. Could look like this:
function doSomething(result) {
// do your stuff here
}
thisLunchQuery.find().then(doSomething)
UPDATE:
In the context of your view, the code could look something like:
render: function() {
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
var self = this;
function assignLunch(results){
var templateArgs = {
thisPlans: this.model.toJSON(),
thisLunch: results
};
self.$el.html(self.template(templateArgs));
}
thisLunchQuery.equalTo("objectId", lunchIdTemp);
thisLunchQuery.find().then(assignLunch);
return this;
}
You can either call a function with thisLunch as a parameter like:
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
thisLunchQuery.equalTo("objectId", lunchIdTemp);
var thisLunch = thisLunchQuery.find().then(function(results) {
funcName(results[0])
});
or put it in the global/window object like:
var thisLunchQuery = new Parse.Query(Lunch);
var lunchIdTemp = this.model.get("lunchId");
thisLunchQuery.equalTo("objectId", lunchIdTemp);
var thisLunch = thisLunchQuery.find().then(function(results) {
window.myLunch = results[0];
});
Related
I have several business objects (with different types) that implement functions for a common object, which is assigned to a property of each business object.
It is possible to call the functions declared on business objects from the common object?
Hereafter some similar code:
var Percent= function(){
this.input= null;
...
this.getValuesRange= function(){
return [min,max];
}
...
}
var Speed= function(){
this.input= null;
...
this.getValuesRange= function(){
return [min,max];
}
...
}
var Input= function(){
this.inputRange= function(){
//here I need to call owner's getValuesRange function
}
}
var input= new Input();
var mySpeed= new Speed();
var rocketSpeed= new Speed();
...
mySpeed.input= input;
rocketSpeed.input= input;
...
facade.enter(mySpeed);
facade.enter(rocketSpeed);
...
For inputRange on Input to access getValuesRange, it has to have access to an instance of Speed. Your code has to provide it that instance, there's no built-in "what object references this object via a property" operation in JavaScript. (If there were, it would have to allow for the fact multiple objects can reference the same object, as in your example — both Speed instances reference the same Input instance.)
This is possible with some workarounds. Here an example:
var c = 0;
var Speed= function(){
var mc = c++;
var _input = null;
var _inputRange = null;
this.getInput= function() {
var self = this;
_input.inputRange = function() {
_inputRange.call(self);
}
return _input;
}
this.setInput= function(input) {
_input = input;
_inputRange = input.inputRange;
}
this.getValuesRange= function(){
console.log("Speed", mc);
}
}
var Input= function(){
this.inputRange= function(){
this.getValuesRange()
}
}
var input= new Input();
var mySpeed= new Speed();
var rocketSpeed= new Speed();
mySpeed.setInput(input);
rocketSpeed.setInput(input);
mySpeed.getInput().inputRange(); // Speed 0
rocketSpeed.getInput().inputRange(); // Speed 1
There are many possible pitfalls with this solution. It's here only tho give an idea.
JavaScript closures - is there any alternative to manually reseting inner variables?
Assuming we have the following closure:
var SearchItemModalModel = (function(){
var filter1;
var filter2;
var filter3;
[...]
var filterN;
var initVariables = function(){
filter1 = undefined;
filter2 = undefined;
filter3 = undefined;
[...]
filterN = undefined;
};
return {
Init: function(){
initVariables();
},
SomeFunction1 : function(){
},
SomeFunction2 : function(){
}
[...]
}
})();
The above is used to display a modal with filterable list of items. Every time user clicks "Show available items" - all filters should be set to undefined. User can display the modal as many times as he/she likes, without reloading the page.
Right now, I reset everything manually, by calling initVariables() inside the Init function - however every time there is a modification to the above JS "class", I have to manually add all new variables to the initVariables() function...
So the question is: is there any better way to do it - so that no manual reseting would be required? At first I thought something like this would work:
var searchItemModalModel = new SearchItemModalModel;
But now, after reading about JS closures, I don't think this is possible - or is it?
Seems to me like you are trying to re-implement objects.
Your example fits itself to the constructor pattern:
var SearchItemModal = function(){
var filter1;
var filter2;
var filter3;
[...]
var filterN;
var initVariables = function(){
filter1 = undefined;
filter2 = undefined;
filter3 = undefined;
[...]
filterN = undefined;
};
this.Init: function(){
initVariables();
};
this.SomeFunction1 : function(){
};
this.SomeFunction2 : function(){
};
[...]
};
Which you then use by creating new instances of it with new:
var searchItemModal = new SearchItemModal();
searchItemModal.Init();
I encourage you to read more about constructors and OOP in JavaScript here, closures are great but there's a reason objects exist, and the way you wrote your code, the filterN variables will stay private either way.
You can use array instead of variables:
var N = 5;
var filter;
var initVariables = function(){
filter = new Array(N);
};
// access variables by it's index (starting from 0)
// e.g.: filter[0]
EDIT: you can also hold all variables in one state object and initialize it with some default state like this:
var defaultState = {
filter1: undefined,
filter2: undefined,
filter3: undefined,
[...]
filterN: undefined
};
var SearchItemModalModel = (function(){
var state = defaultState;
var initVariables = function(){
state = defaultState;
};
[...]
// access variable by object key
// e.g.: state.filter1
I use Knockout.js, and I have an object called letter in my script. That code looks as follows:
function letter(filePath, imagePath, countryId) {
self.filePath = filePath;
self.imagePath = imagePath;
self.countryId = countryId;
}
Then, another place in my code, the following snippet runs:
var uploadedLetter = new letter(data.key,'',59);
viewModel.letters.push(uploadedLetter);
I know that my data.key is a normal string value.
My viewModel code is like this:
var SendWindowedLetterViewModel = function(formSelector, data) {
var self = this;
self.letters = ko.observableArray([]);
}
Applying bindings on my view:
var createLetterData = {
};
var viewModel = new SendWindowedLetterViewModel('#sendLetterForm', createLetterData);
ko.applyBindings(viewModel, document.getElementById('sendLetterForm'));
However, when I look in FireBug after this line has been run, I have the following output:
And I cannot access any of my properties, and if I lookup the object in FireBug, it seems to be 100% empty.
Probably the most simple question ever asked on StackOverflow, but what am I overlooking here?
In letter, you use self.filePath = filePath.
But self isn't defined anywhere in its scope.
So you either do
function letter(filePath, imagePath, countryId) {
var self = this;
self.filePath = filePath;
self.imagePath = imagePath;
self.countryId = countryId;
}
or directly
function letter(filePath, imagePath, countryId) {
this.filePath = filePath;
this.imagePath = imagePath;
this.countryId = countryId;
}
I have a couple of javascript objects that each have a setup method. The code is identical for all of them so I created a function called setupMain. Then for each instance of the object I'm trying to set it's setup value to setupMain. something like below... but when I look at the setup value after an instance is created, it's coming back undefined instead of pointing to the setupMain function. Any idea why? Thanks.
var customObject = function(){
this.title = "";
}
var setupMain = function(obj){
obj.title = "initial setup value";
}
var co = new customObject();
co.setup = setupMain(co);
You might be looking for something like this:
var customObject = function(){
this.title = "";
}
var setupMain = function(){ //"This" will point to instance, such as co
this.title = "initial setup value";
}
var co = new customObject();
co.setup = setupMain; //Reference to function
co.setup(); //Call the setup function
window.alert(co.title);
Also, if you don't want to have to keep setting the setup function each time to create an instance, you can move it to the prototype:
customObject.prototype.setup = setupMain; //Now, every customObject has a setup function
var co = new customObject();
co.setup();
window.alert(co.title);
Finally, if you didn't want to have to call setup(); each time, you can call setup within the constructor:
var customObject = function(){
this.setup(); //Call shared setupMain function because it's part of the prototype
}
var setupMain = function(){
this.title = "initial setup value";
}
customObject.prototype.setup = setupMain; //This can be shared across many prototypes
var co = new customObject();
window.alert(co.title);
Your code evaluates setupMain(co) and assigns the result to c.setup... Therefore:
setupMain sets co.title to "initial setup value"
setupMain returns undefined
co.setup is set to undefined
You should assign the function to your variable, such as:
var setupMain = function() {
this.title = "initial setup value";
}
...
co.setup = setupMain; // Without the ()
I have a class like structure in javascript, Im attempting to invoke a sibling function using a passed in function name.
This is difficulty to explain so let me show you an example of what im trying to accomplish..
function windowFactory(){
this.init = function(functionName,args[]){
SetTimeout(functionName(args),2000)
}
this.func1 = function(var1){
alert(var1);
}
this.func2 = function(var1, var2){
alert(var1+var2);
}
}
var win1 = new windowFactory();
win1.init("func1","hello");
var win2 = new windowFactory();
win2.init("func2","world","!");
Please note that this is only a demo function, syntax errors / typos included.
Now i had this working using a dreaded Eval when it was outside the class...
eval(funcName+"('"+darray[1]+"','"+darray[2]+"')");
It just required it being outside the Class and passed in dummy values for parameters
Something like this should do the trick:
var windowFactory = function() {
var self = this;
this.init = function(functionName){
var args = Array.prototype.slice.call(arguments, 1);
setTimeout(function() {
self[functionName].apply(self, args);
}, 2000);
};
this.func1 = function(var1){
alert(var1);
};
this.func2 = function(var1, var2){
alert(var1+var2);
};
};
var win1 = new windowFactory();
win1.init("func1","hello");
var win2 = new windowFactory();
win2.init("func2","world","!");
Note the custom self reference var self = this;. This is used because when the timed out function is called, the this object will be window (at least in a web browser).
Another clarification: To address a specific object property in JavaScript you can do in the following ways:
object.property; // Or
object['property']; // When you have a string literal, like in your example