I am new to enyo. I want to save a state of variable (which is boolean) while app executes. Then exit the app. After that I want to get the state (true/false) of the variable when app re-opens. How to save and restore the data in enyo?
I would use localStorage (API Docs here) to save your state every time the change in state occurs in your application:
myStateChange: function() {
localStorage.myState = this.myState;
}
Note: to ensure that myStateChange is called every time you set it elsewhere, use this.set() method to set it, not this.myState = newValue;.
Then, in rendered() or create() method I would restore that state from localStorage.
rendered: function() {
this.inherited(arguments); // Call base rendered method
this.myState = localStorage.myState; // Restore your saved value from localStorage
}
There are no special hooks for data storage but it's very easy to tie into the native data storage options available for your platform. You might take a look at these options:
http://dev.opera.com/articles/view/taking-your-web-apps-offline-web-storage-appcache-websql/
http://docs.phonegap.com/en/1.0.0/phonegap_storage_storage.md.html
If you're using enyo.Collection you can get the records from it with collection.raw() and then use JSON.stringify() to get something you can put into localStorage.
You could even use cookies. Hope that gives you some places to start looking from.
Related
I have a firebase realtime database trigger on a create node. my need is to update a property based on some condition in the create trigger for the same object. The way i am doing currently is below:
exports.on_order_received_validate_doodle_cash_order = functions.database.ref("/orders/{id}")
.onCreate((change, context) => {
console.log("start of on_order_received_deduct_doodle_cash")
const orderId = context.params.id
const order = change.val();
var db = admin.database();
const orderRef = db.ref('orders/')
return orderRef.child(orderId).update({"_verifiedOrder": true})
})
As you can see i am getting order id from context and then querying object again and updating it. My question is do i need to do this circus or can i just update it without querying again?
Generally it looks good. Just some small feedback to make you feel more confident about being on the right track.
Call the parameter snapshot instead of change because the parameter name change only make sense for the onUpdate event trigger.
You do not need to log that you're entering the function. Because entering and leaving the function is automatically logged by Firebase also.
You can remove the order variable that is unused.
You are actually not "querying" the object again. Making a reference to a node in the database doesn't make any network call itself. Not until you subscribe to receiving data. So doing orderRef.child(orderId) is not a query, it's just a database reference.
You can use the snapshot's own reference attribute to shorten your code a bit... effectively throwing away almost all code :-)
So your code code look like this instead. It is doing the exact same thing, just shorter. It was also correct from the beginning.
exports.on_order_received_validate_doodle_cash_order = functions
.database
.ref("/orders/{id}")
.onCreate((snapshot) => {
return snapshot.ref.child("_verifiedOrder").set(true);
});
But as mentioned in my comment above, you are effectively just setting a flag that is confirming that data was saved (or rather: confirming that the function was triggered). You might want to add some logic in there to check whether the order can be placed or not and then set the verified flag to true or false depending on that. Because with the logic of the implementation, all orders will have the value _verifiedOrder set to true, which is a waste of storage in your database.
I'm doing the newbie tutorial 'simple-todo' and noticed that once I added security in step 9, I was no longer able to delete tasks created before that.
The issue is that my remove method is checking to make sure that the ID it receives is a string, and the to-do tasks that were made earlier via the console return an object when I use this_.id.
In other words:
Tasks created via the terminal, this._id -> ObjectId("57a128afbe5fd7e7ba9a6fca")
Tasks created with the Tasks.insert method, this._id -> "57a128afbe5fd7e7ba9a6fca"
And the new remove method doesn't like the ObjectId part. How can I get just the ID? I would figure it'd be something like this._id._id, but that's undefined. The workaround was to remove the check from the "remove" method, which is less secure.
Link: https://www.meteor.com/tutorials/blaze/security-with-methods
You can use this._id._str to get the Hex part of the ObjectId.
I would suggest that your method only uses the string, and do a check in the client to see if you need to use this._id or this._id._str
I have the following code:
sub_geo = Meteor.subscribe('geo');
console.log('sub_geo returned from Meteor.subscribe: ');
console.log(sub_geo);
Session.set('sub_geo', sub_geo);
console.log('sub_geo retrieved from Session: ');
console.log(Session.get('sub_geo'));
The output is as follows:
sub_geo returned from Meteor.subscribe:
> Object {stop: function, ready: function}
sub_geo retrieved from Session:
> Object {}
Obviously I need to store the returned subscription handle because I need to call the ready() and stop() functions on it later. Not sure how else to store it other than in the Session. Can I just use a global variable? Also - even if there is some other way of doing it, why doesn't this approach work?
It doesn't work because you can only store EJSON-serializable objects in session variables. If you need the subscription handle outside of the current file, you'll need to store it in a global variable (perhaps under a namespace like Subscriptions - e.g. see richsilv's answer to this question.
You can actually do this, but not the way you would expect.
Just set the Session as you do:
Session.set('sub_geo', sub_geo);
Then when you want to do something with your subscription, retrieve the handle from Meteor's own registry:
const handle = Meteor.default_connection._subscriptions[Session.get('sub_geo').subscriptionId]
And if you ARE going to use the Session (which is not encouraged, except if you really have to), clean it up:
delete Session.keys['sub_geo'];
This is working fine in Meteor 1.3.3.1 for me at the moment, but probably will work for most previous versions as well.
PS: Alternatives for Session are Reactive Var and Reactive Dict.
Is there a way to know when data has been initially fully fetched from the server after running Deps.autorun for the first time?
For example:
Deps.autorun(function () {
var data = ItemsCollection.find().fetch();
console.log(data);
});
Initially my console log will show Object { items=[0] } as the data has not yet been fetched from the server. I can handle this first run.
However, the issue is that the function will be rerun whenever data is received which may not be when the full collection has been loaded. For example, I sometimes received Object { items=[12] } quickly followed by Object { items=[13] } (which isn't due to another client changing data).
So - is there a way to know when a full load has taken place for a certain dependent function and all collections within it?
You need to store the subscription handle somewhere and then use the ready method to determine whether the initial data load has been completed.
So if you subscribe to the collection using:
itemSub = Meteor.subscribe('itemcollections', blah blah...)
You can then surround your find and console.log statements with:
if (itemSub.ready()) { ... }
and they will only be executed once the initial dataset has been received.
Note that there are possible ocassions when the collection handle will return ready marginally before some of the items are received if the collection is large and you are dealing with significant latency, but the problem should be very minor. For more on why and how the ready () method actually works, see this.
Meteor.subscribe returns a handle with a reactive ready method, which is set to true when "an initial, complete snapshot of the record set has been sent" (see http://docs.meteor.com/#publish_ready)
Using this information you can design something simple such as :
var waitList=[Meteor.subscribe("firstSub"),Meteor.subscribe("secondSub"),...];
Deps.autorun(function(){
// http://underscorejs.org/#every
var waitListReady=_.every(waitList,function(handle){
return handle.ready();
});
if(waitListReady){
console.log("Every documents sent in publications is now available.");
}
});
Unless you're prototyping a toy project, this is not a solid design and you probably want to use iron-router (http://atmospherejs.com/package/iron-router) which provides great design patterns to address this kind of problems.
In particular, take a moment and have a look at these 3 videos from the main iron-router contributor :
https://www.eventedmind.com/feed/waiting-on-subscriptions
https://www.eventedmind.com/feed/the-reactive-waitlist-data-structure
https://www.eventedmind.com/feed/using-wait-waiton-and-ready-in-routes
For security reasons, I want to add and remove properties of documents before publishing them to the client, depending on some dynamic calculations. I follow the Meteor documentation and this other SO question.
For example simplicity, say I try to add the following static property to every document (SERVER SIDE ONLY):
var Docs = new Meteor.Collection('docs', {
transform: function (f) {
console.log('Tagging doc: ' + f._id);
f.myProp = 1;
return f;
}
});
For some strange reason, this does not work:
Only some documents trigger the transform function, not all (I can see this through the console logging)
On the client side, none of the documents are tagged with myProp
I haven't tried to put the transform on both the client and the server, because in my real life app I cannot do the necessary computation on the client.
Transform functions on collections are intended for convenience, not security -- note that when you call observeChanges on a cursor, the information is not passed through the transform function (it is passed through the transform when you call observe). The default way of publishing a cursor works by calling observeChanges on it.
If you want to strip off fields of a cursor you're publishing, use the fields option to find on your collection. If you want to do something more complicated, you can explicitly do whatever computation you need if your publish function calls added, changed, and removed itself, instead of returning a cursor. Check out the docs for Meteor.publish for details.