JavaScript subclassing in Parse.com - javascript

In Android I subclassed ParseObject with two local variables that are not in Parse class. I just needed to set those variables locally and had no need to save them on server. They are String's named helper1 and helper2 with getters and setters as well.
It works all fine on Android - I can use setHelper1("whatever"); as well as getHelper() methods on my ParseObject's.
What I want to do is to do the same in JavaScript since I want to make same operation in ParseCloud and make it return results with that additional Strings without creating additional columns in database class.
I read https://parse.com/docs/js/guide#objects-parse-object and https://parse.com/docs/js/guide#queries-basic-queries but it's not helping very much and I can't get it. How that could be achieved?
edit:
q1.find({
success: function(results){
for (var x in results){
x.helper1 = 'foo';
}
response.success(results);
},
error: function(error){
}
});

In JavaScrpt everything is easy. As far as I know, those parse-objects are stored in the form of a JSON object. (equivalently literal objects in JavaScript).
In JavaScript, If you'd like to add an additional property (playing role of a class member) to an existing object, it's enough to use this code.
var myobj = /* This is that parse-object */
// Add property helper1
myobj.helper1 = 'foo';
// Add property helper2
myobj.helper2 = 'bar';
For removing those properties, use this code.
// Remove property helper1
delete myobj.helper1;
// Remove property helper2
delete myobj.helper2;
Equivalently, you can use [] to create and access a property.
// Add property help1
myobj['helper1'] = 'foo';
// Access it
console.log(myobj['helper1']);

I resolved that, by using #Hi I'm frogatto's answers, but it appeared that You can do that on server-side or client-side, but only locally. So when I send data with setted helper1 or helper2 those just vanished so I had to do that operation on client-side which exposes a bit of business logic.
My question is still valid. Still, many of You should get helpful informations from frogatto's answers. Use my answer as a workaround.

Related

What is the purpose of using getters and setters in angular2?

i am new to angular2 and when i was reviewing someone's code, one specific line got me confused
get formData() { return <FormArray>this.lienHolder.get('policyDetails'); }
why is the above line any different from this
formData() { return <FormArray>this.lienHolder.get('policyDetails'); }
I searched about this in google and found no actual results, can anyone help me to understand this.
UPDATE
what is the difference between this
var obj = { log: 0, get latest() { return this.log++; } };
and this
var obj = { log: 0, latest() { return this.log++; } };
both are giving me the updated value all the time i call them
obj.latest & obj.latest() -- returns updated result all the time then why use one over another?
get formData()
is called a getter accessor. It allows you get the property dynamically. It always should return a value.
https://www.typescriptlang.org/docs/handbook/classes.html
TypeScript supports getters/setters as a way of intercepting accesses
to a member of an object. This gives you a way of having finer-grained
control over how a member is accessed on each object.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
Sometimes it is desirable to allow access to a property that returns a
dynamically computed value, or you may want to reflect the status of
an internal variable without requiring the use of explicit method
calls. In JavaScript, this can be accomplished with the use of a
getter.
In opposite to that, getFormDate() is a function, it can take arguments and not always returns values.
One of the cases, where I like to use a getter is when a property should be get from a service:
<p>{{dictionary.label1}}</p>
and then I get it from a service like this:
get dictionary(){
return this.myService.getDictionary();
}
this way when the service changed the data I dynamically can receive the value to my binding/model.
If I would have defined as the following:
dictionary: [];
ngOnInit(){
this.dictionary = this.myService.getDictionary();
}
then I would be 'stuck' with the old data while the service already received the new set of data. Of course, you can then set a change listener and trigger the update, but it's more code!
Think of getters as dynamic class properties.
UPDATE:
For the examples in your updated post, it's true, they give the same result, and it's a good thing! You can use both, but as they don't work similarly, you can have more options in some cases. It's not like only one or only the other, or which one is the best. In most of cases you can use both, it's where and for what you need to use them. Most of the times, it's a method which is used, as it has more comprehensive use: we use methods with or without parameters, to trigger actions on objects. But in some cases, again, it will not have the same flexibility as a getter. If you are hesitant which one to use, use the method first and when you see its limits, think if the getter would help you, as now you know what's its purpose, which is - a property, but dynamic!
An other example:
isShown:boolean; //is 'static', will return the same value unless you change it in some kind of a method
get isShown(){
return this.someCondition && this.someMethodResult() || this.anotherCondition
}
If someCondition and anotherCondition change and the result from someMethodResult had to come changed you don't have to request isShown value, it's done dynamically.
Opposite of that, you can have
setShown(){ //the method
this.isShow = !this.isShown;
}
Here setShown needs to be called so isShown could be updated.
Also, a getter can easily replace a method which only job is to return a class property value.
UPDATE2:
An other 'good' example for get. A case when a component needs to check if the user is logged to show/hide some buttons. Instead of subscribing to changes, you do:
HTML:
<button [hidden]="!isLogged">Log out</button>
Typescript:
get isLoggedIn(){
return this.authService.isLoggedIn();
}
And that's it! If the user is logged out the button will be disabled 'immediatly'. No nead for the heavy subscribe/unsubscribe...
with the get you can treat it like a var:
let something = formData;
otherwise you must invoke the function:
let something = formData();
You would use a get usually to format data as you retrieve it. for example:
let _number = '12';
get number(){
return parseInt(_number);
}

Avoiding duplication of key/data

I have a design annoyance with some existing code in JS. The code is working, so I have no desperate hurry to change it, but the duplication shown below does annoy me. What is the usual/recommended/official way of avoiding this situation?
The actual system is a large/complex financial system, so I have simplified it to the most basic example which demonstrates the problem:
var colours={
red:{id:"red", vals:[1,0,0]},
green:{id:"green", vals:[0,1,0]},
grey:{id:"grey", vals:[0.5,0.5,0.5]}
// ...etc
};
// id needs to be known internally within the object - thus it is defined as a property.
// e.g:
colour.prototype.identify(console.log(this.id));
// id also needs to be used externally to find an object quickly.
// e.g:
function getcolour(s){return colours[s];}
// Although this works. It does mean duplicating data, with the theoretical possibility of a mismatch:
var colours={//...
blue:{id:"green", // oh dear...
How would this normally be handled by the experts?
This question is somewhat subjective.
When creating my applications I typically try do do the following:
never define same data in multiple places. source should always be unambiguous
if I need to create any indices for faster/easier access, I use utility methods to do it. Those methods should be properly unit-tested, so that I would have little doubts on them doing the wrong thing
use third party libraries as much as possible (such as already suggested lodash or underscore) to minimize the amount of code to be written/maintained.
If your algorithms and utilities are properly unit-tested you should not worry (too much) about getting the data into inconsistent state. However, if those are critically important systems/interfaces, you may add some validation on output. And it is generally a good practice to have data validation and marshaling on input.
Explanation on the utility methods:
if you have data array, say
var data = [{"id":"i_1", ...}, {"id":"i_2", ...},{"id":"i_3",....}];
Then and you have to create an index out of that or create more data sets based on the original array, then you create yourself a library of utility methods that do the modification on the array, create derivative data sets, or iterate on the array and create a resulting item on the fly. For example:
var createIndex = function( arr ){
// do something that converts the data array with expected structure to object
// {
// i_1: {"id":"i_1", ...},
// i_2: {"id":"i_2", ...},
// i_3: {"id":"i_3", ...}
return newObj;
}
This method will create a hash-map to access your data, which is faster then to iterate over the original array all the time. But now, this method you can easily unit-test and be sure that when you use it on the source data to get your intended dataset, there will be no inconsistency.
I wouldn't change the colours[key] direct access with other method to avoid duplication.
Any other attempt will lead to processing and you have mentioned that you have a large amount of data.
I assume that the duplication is over the incoming data that is a waste.
An example of processing over the network data consuming could be, going over the map object and set the id dynamically according to the key. (processing vs traffic)
colours[key].id = key
You can filter your object converting it to an array of objects and then filtering unique values. Converting it to an array would allow you to perform a lot of operations quicker and easier.
So you can map your object to an array:
var coloursArray = myObj.map(function(value, index) {
return [value];
});
Remove duplicates:
function removeDuplicates() {
return coloursArray.filter((obj, pos, arr) => {
return arr.map(mapObj => mapObj[id]).indexOf(obj[id]) === pos;
});
}
You can remove duplicates from an array using for example underscore.js through the .uniq method:
var uniqueColoursArray = _.uniq(coloursArray , function(c){ return c.id; });
Moreover, this function is pretty useless because you can access your element directly:
function getcolour(s){return colours[s];}
Calling colours[s] it is also shorter than getcolour(s). Your function would make sense if you pass also the array because it is not accessible in some other scope.
Then I can't understand why you do pass a console.log as parameter here:
colour.prototype.identify(console.log(this.id));
maybe you would like to pass just the this.id

Object.assign not working as expected

I have one object called bookings, and inside it I have several properties, and i want extend with Object.assign, like this:
let data = Object.assign(booking, {
hiw: event.hiw[booking.locale],
tip: event.tip[booking.locale],
start: moment(event.start).format('L')
});
But when I print the data, the result will be the same object from the source (booking), so hiw, tip and start will be ignored, but... if I try to do:
let data = Object.assign({}, {
hiw: event.hiw[booking.locale],
tip: event.tip[booking.locale],
start: moment(event.start).format('L')
});
This will work perfect.
My question is: what am I doing wrong here? Why can't I extend booking and I can extend the empty object?
That's definitely not a problem with async code, when i try to extend booking, he already exist with all properties inside.
I also was trying to use underscore extend method, and the behavior is exactly the same.
Mongoose documents (model instances) are special: they will only print properties that are present in the schema.
If properties aren't defined there, they won't show up when you console.log() them (and also not if you convert the document to a plain JS object with obj.toObject()).
This means that using Object.assign() will only work if you assign properties that are also present in the schema. Any properties that aren't declared will not be shown (nor saved to the database).
If your intention is to use the document for output, you should convert it to a proper JS object first before assigning to it:
let data = Object.assign(booking.toObject(), {
hiw : event.hiw[booking.locale],
tip : event.tip[booking.locale],
start : moment(event.start).format('L')
});

Setting Object to Chrome Storage

So I'm trying to save an object via the chrome.storage API. The relevant code is:
var images = null;
var storage = chrome.storage.sync;
var key = "key";
images = getImages(source);
alert(images.length); // returns 4
storage.set({key: images});
storage.get("key", function(result) {
alert(result.length); // returns undefined
});
I'm tested that immediately after the getImages() function, images is a wrapped set JQuery object with a length of 4. However, when I try to access images.length via the storage.get callback, the result is undefined.
Could someone help identify the error in how I am storing and/or retrieving this JQuery object?
Update 1:
Thank you all for your help. As clarification for the use case, I am using chrome.storage instead of localStorage because I plan to pass extension info to another script.
Fortunately, TranQ/Xan's solution has enabled me to access the array via the storage.get call.
I'm still experiencing issues working with the wrapped set JQuery object stored in the array but I'll post a separate question since the current solution encapsulates broader use cases.
TranQ's comment is on point.
Presumably, images is an array. You store that array under the "key" key.
When you execute the get() function, it returns an object populated with all key-value pairs you asked, even if you only ask for one key.
So, result is an object {key : [/* something */]}. Objects do not have a length property, and you get undefined
You need to use result.key (or result["key"]) to access your array.

javascript variable variable names and global scope (pinesnotify)

I'm using pines notify (somewhat irrelevant to my issue, I imagine) to create notifications on the change event of a drop down list. On the server side, the change is saved to a database, then when the save is complete - I wish to remove the notification (or do something else depending on the result).
The problem is in creating the notification object in a way that I can later reference it (to remove it).
My intended solution would obtain the id of the dropdownlist, prepend 'pn' to it and use that as the variable name, much like
var pnid = 'pn' + $('#mydropdown').attr('id');
notifications[pnid] = createNotification();
In the codebehind I can create javascript code knowing what the notification object will be called. However I'm struggling with my 'notifications' object.. I've tried this[notifications], window[notifications] etc. to no avail (ie I cannot later reference this object to interact with it) . I'm creating that object outside of any functions like so
var notifications = {};
Am I going about this the completely wrong way?
You can use this line before reaching notifications object.
window.notifications = window.notifications || {};
This will help you create the object if it is undefined and it will also prevent you from overriding it if it already exists.
Note : I assume you have to use this object as a global variable.

Categories

Resources