Listen for firebase-document synced - polymer

How do you know when the Polymerfire firebase-document element is synced?
To be specific the firebase-document binds with an object via its data attribute. The value of this object goes from undefined --> { } --> {actual persisted data}.
How can you listen for firebase-document completing it's instal data fetch from the server. I am trying to check if there is data written at that location.

There is an issue open for this on GitHub. It is an unfortunate side effect caused by the solution to some other problem the author was trying to solve.
For now, all you can do is check that the object is empty (something like Object.keys(obj).length === 0) and do nothing if so.
You can't store an empty object in firebase, so if the data you are given is {}, you usually know it hasn't loaded yet.

Related

Couchbase Sync-Gateway Multiple Clients

I'am currently playing around with the Couchbase Sync-Gateway and have built a demo app.
What is the intended behavior if a user logs in with the same username on a different device (which has an empty database) or if he deleted the local database?
I'am expecting that all the data from the server should get synced back to the clients.
Is this correct?
My problem is that if i'am deleting the database or login from a different device, nothing will get synced.
Ok i figured it out and it's exactly how i thought it would be.
If i log in from a different device i get all the data synced automatically.
My problem was the missing sync function. I thought it will use a default and route all documents to the public channel automatically.
I'am now using the following simple sync-function:
"sync": `function (doc, oldDoc) {
channel('!');
access('demo#example.com', '*');
}`
This will simply route all documents to the public channel and grant my demo-user access to it.
I think this shouldn't be used in production but it's a good starting point for playing around.
Now everything is working fine.
Edit: I've now found the missing info:
https://docs.couchbase.com/sync-gateway/current/configuration-properties.html#databases-this_db-sync
If you don't supply a sync function, Sync Gateway uses the following default sync function
...
The channels property is an array of strings that contains the names of the channels to which the document belongs. If you do not include a channels property in a document, the document does not appear in any channels.

Data Binding at wrong time in Jstree

Using jstree v3 I have
this.elements.$tree.jstree({
core: {
data: function (node, successCallback) {
// Handle node expansion
thisTmp._expandNode(node, successCallback);
},
...
This works fine the first time I open a node and goes to my server and gets the child nodes. If I then close the node it is also called and I'd like to not bother the server at that point. Additionally if I then re-open the node this function is not called at all.
Investigating I noticed that the node passed always has a state of loading: true with all others set false.
Further investigation shows that this function is called before the before_open.jstree event, and after the after_close.jstree event. This probably explains the node state but doesn't help me.
I need it to call the webserver every time I open the node because the items represented by the child nodes may have changed since the last time you looked. That is there may be more/different/fewer nodes.
Spent all morning on this and can't see what I'm doing wrong (or should do differently). Any ideas?
Thanks
OK I've found a solution...
In the after_close event I set the node's loaded state to false. This causes jstree to trigger the loading again when I next open the node and I get any updated tree items.

How to persist my custom data with app-indexeddb-mirror in Polymer

I'm using the app-indexeddb-mirror component for storing offline data in the indexeddb cache. I got it working with the following code.
<app-indexeddb-mirror
key="travels"
data="{{data}}"
persisted-data="{{persistedData}}">
</app-indexeddb-mirror>
<firebase-query
app-name="projectMeta"
path="/travel"
data="{{data}}">
</firebase-query>
This code block successfully get an array of data and then stores it under the travel key in my indexeddb.
Let's say I'm offline and I want to fill in a form which is then stored in indexeddb under the key bto. How can I get the component to persist my data?
I tried the following:
<app-indexeddb-mirror
id="readCache"
key="testKey"
data="{{liveData}}"
persisted-data="{{persistedData}}"
log="true">
</app-indexeddb-mirror>
First attempt to write my data object:
this.$.readCache.setStoredValue(key, data).then(function(res) {
console.log("success")
});
Second attempt to write my data object:
this.set("liveData", newval.data);
in the console i'm getting:
but when I'm looking in the console under the Application tab to view all the stored content under indexeddb, it's still empty?
For what I have seen, you can't really "save" offline data with this component. It will update the versions of the data each time they change, and save them, and on an offline scenario will only serve the stocked value in persisted data, but not save them.
In fact, as soon as you'll be online again, all changes will be erased by the online version of the datas retrieved by the firebase-query
If you want to save offline changes, you'll have to use the component serving the datas, fortunately firebase-document have offlines capabilities so just save your data with it, and it should work fine.
At least that what's I have done on a pet project, and it seems to work.
Cordially :)

SharedObject: can receive event from other clients but never fires event after saving data

I'm using a SharedObject to create a simple chat app. The SharedObject was created fine and my app could receive the sync event when other clients updates the data on the SO. However, the problem comes when my app tries to saves the data on the SO to signal other clients. I've verified that the data was changed using the following code:
trace("before:"+so.data.chatMessage);
so.data.chatMessage = msg.text;
trace("after:"+so.data.chatMessage);
It said "before:abc" and "after:def". Unfortunately no clients received the sync event after the data on the SO changed including the client that made the data change itself. So this means this client can receive other client's message but itself message never gets out.
Anybody has seen such issue before? Thanks,
Jack
You have to call flush():
If you don't use this method, Flash Player writes the shared object to a file when the shared object session ends — that is, when the SWF file is closed, when the shared object is garbage-collected because it no longer has any references to it, or when you call SharedObject.clear() or SharedObject.close().
or
use setProperty() to change the property:
Updates the value of a property in a shared object and indicates to the server that the value of the property has changed.
As you only change a property of the data object, there's no notification going on that this value has changed.
Calling so.flush() resulted in "Error: Error #2130: Unable to flush SharedObject." It did not print an internal error, though. So it seems the problem was the flush couldn't be successful... Any idea how could happen?
Take a look at this other question:
Error #2130 Unable to flush sharedObject

How to load angular-formly vm.fields object from remotely-generated json?

In my application I have dynamic field sets on what is otherwise the same form. I can load them from the server as javascript includes and that works OK.
However, it would be much better to be able to load them from a separate API.
$.getJSON() provides a good way to load the json but I have not found the right place to do this. Clearly it needs to be completed before the compile step begins.
I see there is a fieldTransform facility in formly. Could this be used to transform vm.fields from an empty object to whatever comes in from the API?
If so how would I do that?
Thx. Paul
There is an example on the website that does exactly what you're asking about. It uses $timeout to simulate an async operation to load the field configuration, but you could just as easily use angular's own $http to get the json from the server. It hides the form behind an ng-if and only shows the form when the fields return (when ng-if resolves to true, it compile the template).
Thx #kent
OK, so we need to replace the getFields() promise with this
function getFields() {
return $http.get('fields-demo.json', {headers:{'Cache-Control':'no-cache'}});
}
This returns data.fields so in vm.loadingData we say
vm.fields = result[0].data;
Seems to work for OK for me.
When testing I noticed that you have to make sure there is nothing wrong with your json such as using a field type you haven't defined. In that case the resulting error message is not very clear.
Furthermore you need to deal with the situation where the source of the data is unavailable. I tried this:
function getFields() {
console.log('getting',fields_url);
return $http.get(fields_url, {headers: {'Cache-Control':'no-cache'}}).
error(function() {
alert("can't get fields from server");
//return new Promise({status:'fields server access error'}); //??
});
.. which does at least throw the alert. However, I'm not sure how to replace the promise so as to propagate the error back to the caller.
Paul