0

On the first load of the page after a user login event, I want to populate the items property with a set of objects stored in my Firebase.

A achieves my desired behavior.

A
<firebase-query
    id="query"
    ...
    path="users/[[user.uid]]/widgets"
    data="{{items}}">
</firebase-query>

B does not.

B
<firebase-query
    id="query"
    ...
    path="widgets"
    data="{{items}}">
</firebase-query>

When using B, I expect to see the items object populate, but instead the items object is null. However, if I refresh the browser manually (without logging out) the element behaves as expected. However, if I log out (then refresh while logged out), the problem reappears until I reload again. If I only log out then log back in the problem does not reappear due, I think, in part to the fact the app does not reset as described here.

Why does A work? But not B? And what modifications must I make to B to get it to work? (Because I want to store the widgets from the root/widgets/ path and not have to store that detail under the users/... path.

Previous Unsuccessful Attempts

My current (unproven) theory is that the in the case of B (when the URL is constant/static, i.e., widgets/) firebase-query gets involved in some sort of race condition; and only fetches the data after some lifecycle event and doesn't attempt to re-fetch the data. On the other hand, the firebase-query does attempt to re-fetch when the path is dynamically updated based on the databinding in the path attribute (i.e., path="users/[[user.uid]]/widgets"). Is this theory correct? Or is there some other cause? Do I need to imperatively fetch the data after some event? If so, how can I accomplish all this?

I have tried the following ideas without success.

C
user: {
  type: Object,
  notify: true,
  observer: '_userChanged',
},

_userChanged: function() {
  this.$.query.path = 'widgets';
  var items = this.$.query.ref.child('widgets');
  this.set('items', items);
},
D
<firebase-query
    id="query"
    ...
    path="[[path]]"
    data="{{items}}">
</firebase-query>

<script>
...
  properties: {
    path: {
      type: String,
      value: function() {
        return 'widgets';
      },
    }
  },
...
</script>

Also, on the Polymer Slack Site, @will-in-china says:

I have had problems with the data loading the first time, I found that if i don't have more than one reference to the same path, i dont get this issue.

I'm not sure what that means in this context as I only have one reference in my element (and app) to the path path="widgets" inside a firebase-query element.

Community
  • 1
  • 1
Let Me Tink About It
  • 15,156
  • 21
  • 98
  • 207
  • have u rule out the localhost issues related to http /cache on the fetch? i dont think it would be that but , at least put aside the standard issue of making sure your browser is config'd so that caching is not throwing an additional wrench in things. – Robert Rowntree Dec 04 '16 at 08:58
  • is there any XHR code associated with the Fetch? I say that because i think in the template code you can manually fire/retrigger the Fetch on [[items]] instead of rely on the documented lifecyle observers on bound objects? – Robert Rowntree Dec 04 '16 at 09:06
  • @RobertRowntree: Strike my earlier comment. I have not found a solution yet. I only thought I did. No, there is no XHR code associated with the fetch. Can you please explicate your idea in your second comment? And how would I rule out localhost issues? I mean, I cleared the cache but is there anything else I can do beyond that? The problem still persists. – Let Me Tink About It Dec 04 '16 at 10:54
  • u might go over to the 'slack' at : https://polymer-slack.herokuapp.com/ – Robert Rowntree Dec 04 '16 at 14:27

3 Answers3

0

i dont think this is your specific issue but it may be similar in that after a login -> setNewRoute(nextPage) i did not get a render and i changed the subsequent template ( Iron-Ajax ) to fire manually rather than via the observer.

  loggon: function parseLogin(user, password) {
...

     Parse.User.logIn(_user, _pass).then(function() {
      page('/channels');

---
channels.render ...

      _render: function() {
        console.log('_render');
        this.$.get_channlinq.headers = hdr;
        //xhr params
        var body = this._setQry(this.params.channelId);
        this.$.get_channlinq.body = JSON.stringify(body);
        //fetch , load , template will render
        this.$.get_channlinq.generateRequest(); 
Robert Rowntree
  • 6,230
  • 2
  • 24
  • 43
0

"When using A, I expect to see the items object populate, but instead the items object is null. However, if I refresh the browser manually (without logging out) the element behaves as expected. However, if I log out (then refresh while logged out), the problem reappears until I reload again."

I'm seeing similar behavior in my app. In my case, it is related to firebase-auth and firebase-query race conditions. In my case,

  1. When I login, the firebase-auth is firing at the same time/after firebase-query. In this case, my query is rejected because of invalid permission - I am querying before being authenticated. Error log excerpt:

    "detail: Error: permission_denied at /parents: Client doesn't have permission to access the desired data. …, type: "error", target: firebase-query .... firebase-query does not retry after authentication is complete. I don't know if this is a bug.

  2. When I refresh after logging in, since I am already authenticated, the query is successful.

To debug this issue, I added a on-error handler to print out the permissions. To get around this issue, I am using the disabled property. When the page is first loaded, all queries are disabled. Only when authentication is successful, I toggle "disabled" at which point queries fire successfully.

signIn: function(){
  var email = this.user.email;
  var password = this.user.password;
  this.$.auth.signInWithEmailAndPassword(email, password)
     .then(function(response){
  self.disabled = false;
  // console.log('signin', response);
  })
 .catch(function(error){
  console.log('auth-element:signIn error is', error.detail);
  })
 .then(function(){
    // call other functions
 });
 },
handleError: function(error){
  console.log('error message', error.detail.message);
},
<firebase-query
   id = "query"
   app-name="my-app"
   path = "/shoeboxes"
   data = "{{datauid}}"
   on-error="handleError"
   disabled="{{disabled}}">
</firebase-query>

Hope this helps. Basically, I'm finding that with polymer and firebase, promises are better than automagical bindings...

-1

I'm coming late but I resolve this using dom-if condition if user this prevent make a request if no are an user authenticate

Neiro
  • 66
  • 4