Firebase realtime database + JS object - javascript

I have a really simple JS code:
var worldRef = firebase.database().ref('something/something1');
var something = new Object();
worldRef.on('child_added', function(snap) {
something.id = snap.key;
something.value = snap.val().value;
});
console.log(something);
It works almost fine - just one key&value from database, but it's something. If I modify it:
console.log(something.id);
Undefined. I've tried with map instead of object, but same. I see everything in map, but when I try to call the getmap(key), it's undefined.
Array-based solution:
var worldRef = firebase.database().ref('something/something1');
var something = [];
worldRef.on('child_added', function(snap) {
something.push ({
id: snap.key,
value: snap.val().value
})
});
console.log(something);
It works.

This is because each time a child is added, you re-assign the id and value properties of your something object.
Since, the child_added event is triggered once for each initial child at this location (see the doc), at the end your object just contains the last children element.
If you do as follows (creating a new property for each child), you will see the same effect than with the Array:
var something = new Object();
worldRef.on('child_added', function (snap) {
something[snap.key] = snap.val().value;
});

Related

How to get data as Object from dataTransfer?

I do the following:
const blockOrField = new Block();
ev.dataTransfer.setData("data", blockOrField);
When I get data in another place:
cosnt data = e.dataTransfer.getData("data");
I get data as [object Object] instead real instrance.
Before passing to data I see that it is instance:
if (blockOrField instanceof FieldDefinition) {
alert("works");
}
ev.dataTransfer.setData("data", blockOrField);
I know it should be serialized to string JSON, but I have complicated instance with composition.
If you look at the documentation for setData() it specifically says "A DOMString representing the data to add to the drag object.". So you are out of luck trying to store an object reference there.
What I would do here is create a another object somewhere and store the needed reference there with an id.
const dataTransferCache = {};
function onDragStart(ev) {
const block = new Block();
const id = GetRandomId(); // Just get an id somehow
dataTransferCache[id] = block;
ev.dataTransfer.setData("data", id);
}
function onDragEnd(ev) {
const id = ev.dataTransfer.getData("data");
const block = dataTransferCache[id];
delete dataTransferCache[id]; // Remove the value again
}
This would even support multi touch dragging if that is somehow needed. If this needs to be shared between components you could simply put the dataTransferCache in a separate file and include a reference to in in both components.

setState is not updating the state, even in its callback react-native

here the user_res is updated but not the state, and I have tried binding this function to this also. but same result :(
let user_res = usr_vote;
user_res.map((vote)=>{
if(vote.id==dat_id){
vote.status = stats
}
})
console.log("update user response:",user_res)
this.setState({user_response:user_res},()=>{
console.log("but this is not uodating : ",this.state.user_response)
});
I don't think even user_res is updating. map doesn't update the original variable. You need to assign the value of .map to something.
user_res = user_res.map((vote)=>{
if(vote.id==dat_id){
return {...vote, status: stats}
} else {return vote}
})
If you check documentation form Array.prototype.map(), you will see that map doesn't modify the original array, it returns a new array with the modified items.
The map() method creates a new array with the results of calling a
provided function on every element in the calling array.
So with that information you can modify your code accordingly,
// create a new array with the modified items
let user_res = usr_vote.map((vote) => {
if(vote.id == dat_id){
vote.status = stats
}
});
// update state with the new array
this.setState({user_response:user_res},()=>{
console.log("but this is not uodating : ",this.state.user_response)
});
PS: stats is not defined anywhere in your snippet. If you are not defining it somewhere in your code that your shared snippet doesn't contain, it is OK but otherwise you need to fix that part too.

define argument list for function in javascript

I'm sorry if this is a duplicate, but i really don't actually know how to even ask this question. I'm coming from a native language background where you have control of how parameters are pass (by value, reference or pointer), and even though i've been using javascript for many years, i still have a tough time with knowing when variables are being passed by reference or value sometimes.
I'm would like to allow a function to be overridden in a javascript class, but basically i'm having a problem passing the arguments as a reference to the function.
I'll have to provide an example because i don't know exactly how to explain this.
So i have a "class", i'll call it exampleClass:
exampleClass = function()
{
var m_largearray = [];
var m_width = 100;
var m_funcParams = {data: m_largearray, width:m_width};
var m_someFunction = function(_params){
// do stuff
}
var m_finalValues = [];
return {
doProcessing: function()
{
// do some things
m_finalValues = m_someFunction(m_funcParams);
// do stuff with the m_finalValues
}
setFunction: function(_func, _params)
{
m_someFunction = _func;
m_funcParams = _params;
},
largearray: m_largearray,
width: m_width
}
}
So this class has a function which gets called, doProcessing(). Inside this function, it calls another function that does part of the processing, but i would like to have control of this part of the processing outside the class when i do not want the default way to process the data.
So something like this:
var classinstance = exampleClass();
var somespecialarray = [];
var someint = 5;
var somewidth = 900;
classinstance.setFunction(function(_params){
// do some processing with different set of params
// even though somewidth was set to 400, i will still get _params.width = 900 here
// return some array
},
{data:somespecialarray, anint:someint, width:somewidth});
somewidth = 400;
classinstance.doProcessing();
This is just a complete example of what i'm trying to do, i just wrote this code here off the top of my head so if theres errors thats why.
Anyway, the problem with this is that the parameter list i set (i've tried using an array instead of an object). When i set m_funcParams, it seems the data is copied rather than referenced. When i change these arguments, m_largearray for example, when the default function gets called, the parameter data is what it was when i originally set m_funcParams, and not what i have updated m_largearray to be, the same as when i override the function, if i change somewidth from 900 to 800, when i call the function, the width parameter i still 900.
I hope this makes sense, i just need some clarity on why the function is not getting the updated values, and if there is a better way of doing this.
So, why is the function not getting the changed values, and is there a better way of doing this?
EDIT:
Here is a complete working example. I think i just realized when i set the variable to be something else, i'm basically losing a "pointer" to the value it was before. if i set an element in an array, it updates in the function, but if i set the whole array, it does not
<html>
<body>
<script>
var exampleClass = function()
{
var m_largearray = [1,2,3];
var m_width = 100;
var m_funcParams = {data: m_largearray, width:m_width};
var m_someFunction = function(_params){
// do stuff
alert(_params.data[0]);
}
var m_finalValues = [];
return {
doProcessing: function()
{
// do some things
m_finalValues = m_someFunction(m_funcParams);
// do stuff with the m_finalValues
},
setFunction: function(_func, _params)
{
m_someFunction = _func;
m_funcParams = _params;
},
largearray: m_largearray,
width: m_width
}
}
var classinstance = exampleClass();
classinstance.largearray[0] = 3;
classinstance.doProcessing();
classinstance.largearray = [7,8,9];
classinstance.doProcessing();
var somespecialarray = [4,5,6];
var someint = 5;
var somewidth = 900;
classinstance.setFunction(function(_params){
// do some processing with different set of params
// even though somewidth was set to 400, i will still get _params.width = 900 here
alert(_params.width);
// return some array
},
{data:somespecialarray, anint:someint, width:somewidth});
somewidth = 400;
classinstance.doProcessing();
</script>
</body>
</html>
I hope I understood correctly and that this helps.
First of all when you pass an object to a function it passes as a reference, so changing one of it's properties will change the referred object's property.
However, when you invoked classinstance.setFunction in your example, you passed an object with a property width which recieved the variable somewidth, which is not an object so it gets passed by value.
Finally, when you changed someWidth to 800 you only changed someWidth, because width was passed as a value.
Edit:
In addition, when invoking classinstance.setFunction, you passed a function with param _param which is not part of that scope.

Ext js store has Many copy to another store

I have data store "a" with hasMany attribute,trying to create new store "b" by copying hasMany records of "a" with below code,but when i use b store for combo box it throws error saying record.length is undefined
var b = Ext.create("Ext.data.store"{
model:'service'});
Ext.getStore("a").each(function(record,id){
for(var i in record){
b.add(record.raw.subservice);
}
})
It works for me, try this. I hope it helps.
function deepCloneStore (source) {
var target = Ext.create ('Ext.data.Store', {
model: source.model
});
Ext.each (source.getRange (), function (record) {
var newRecordData = Ext.clone (record.copy().data);
var model = new source.model (newRecordData, newRecordData.id);
target.add (model);
});
return target;
}
Original source code reference.
You are trying to iterate store, instead you need to iterate store.data.items.
And you do not need for cycle for record.
Try this
var b = Ext.create("Ext.data.store"{
model:'service'
});
Ext.getStore("a").data.items.each(function(record,id){
//You can add multiple records by calling .add method once
b.add(record.data.subServiceItems);
});
Write if this does not help.

Modifying javascript class attributes

What i am trying to do here is, I have the following class Session
function Session(){
this.accounts = {};
this.setupAccounts = function(res){
this.accounts = res;
log(res);
log(this.accounts);
};
this.test = function(){
log(this.accounts);
};
}
The class Session has an attribute accounts, which will keep store certain data. But in order to initialize it, i initialize it as an empty object.
Next I call the method setupAccounts to modify the value of accounts. For example, I read a file, load it's data and then store that data inside accounts.
But I am having scope problems.
For example the following code :
var session = new Session();
var user_account_path = '/adata/user_accounts.json';
loadJsonFile(user_account_path)
.then(session.setupAccounts);
session.test();
So what i am doing in the code above is fetching the contents of a file as a Json Object and then I am passing that data to the method setupAccounts in order to store that data in the variable accounts. But my output looks like the following:
Object {arjrule3: Object} // printing the json object read from file
Object {arjrule3: Object} // locally changed value of accounts
console.log(session.accounts) // printing global value of accounts
{} // value has not changed.
What am i doing wrong? Why isn't the value for accounts changing for the object session ?
Something Funny just happened, if i write the code as the following:
var session = new Session();
var user_account_path = '/adata/user_accounts.json';
loadJsonFile(user_account_path)
.then(function(res){
session.setupAccounts(res); // Change Here
});
Output:
Object {arjrule3: Object}
Object {arjrule3: Object}
session.accounts
Object {arjrule3: Object} // works! Why ?
It works, why is it so ?
var session = new Session();
var user_account_path = '/adata/user_accounts.json';
loadJsonFile(user_account_path)
.then(session.setupAccounts);
session.test();
In the above example you're just passing the function "setupAccounts" as the callback. You would need to bind it first e.g.
var session = new Session();
var user_account_path = '/adata/user_accounts.json';
loadJsonFile(user_account_path)
.then(session.setupAccounts.bind(session));
session.test();
The other example you've added works because you're calling the "setupAccounts" function on the session object, not just passing a reference to it.

Categories