Polymer + Firebase (Polymerfire): not w

2019-01-24 19:04发布

问题:

I'm trying to push data to Firebase using Polymerfire and the Polymer App Toolbox template:

  • my-app.html contains a configured <firebase-app> component.
  • my-models.html (which is a page configured in my-app.html routes) contains a <add-model> component
  • <add-model> is a form with a <firebase-query>, <firebase-auth>, input, and submit button.
  • I attempt to push data using <firebase-query> with the following function in the add-model.html Polymer object:

    Polymer({
        is: 'add-model',
        properties: {
            data: {
                type: Object
            }
        },
        create: function() {
           this.$.query.ref.push({
               name: this.$.myModelName.value
            });
        }
    });
    

    Outcome

  • Calling push on the <firebase-query> object in add-model.html returns Cannot read property 'push' of undefined (explained in this Q/A, in our case it's because <firebase-app> does not appear to be properly declared).

  • Moving <firebase-app> from my-app.html to add-model.html file does make the push function work, but then my-app.html loses its Firebase functionality.
  • Calling <firebase-app> in both my-app.html and add-model.html returns Uncaught Error: Firebase App named 'firebase-app' already exists.
  • <firebase-auth> does work in add-model.html and returns a [[user]] object.

How do I make firebase-query properly communicate with firebase-app from my route?

回答1:

TLDR: The solution is to import polymerfire/polymerfire.html (even if not all elements used in that file) in the same file as your <firebase-app> declaration.


Your my-app.html probably imports polymerfire/firebase-app.html (and no other imports from Polymerfire); and my-models.html probably imports only polymerfire/firebase-query.html and polymerfire/firebase-auth.html, assuming those are the only Polymerfire elements used in that file.

I've identified the cause (but not necessarily the root cause). The symptoms are exhibited when polymerfire.html is not imported in the same file as the declaration of <firebase-app>.

polymerfire.html imports all elements from Polymerfire, including Polymer.FirebaseCommonBehavior, which defines the app property seen in all Polymerfire elements. I'm guessing the Firebase SDK requires all Polymerfire elements imported before app initialization in order to populate the app object appropriately. Otherwise, when firebase-query initializes, app.database will be undefined, which prevents its ref property from initializing, leading to runtime errors when you try to use the methods of the Polymerfire elements. In the case of this.$.query.ref.push(...), the error seen would be:

Uncaught TypeError: Cannot read property 'push' of undefined


回答2:

I found the above answer to import polymerfire/polymerfire.html right on the money. Additionally I would add that my particular app was very very fussy about exactly where every import and firebase element was located. Most of the polycasts (such as #58 referenced above) seem quite straightforward and easy to get right. This particular one took a lot of experimentation with where the elements and imports were located, due to scoping or visibility or other issues that I never figured out.

Hope this helps someone else in the same situation I was in.

I'd also bet that a visitor in 2018 or later would find this post obsolete, because it would seem likely to be improved by then.



回答3:

For me the key was to declare firebase-app before declaring the rest of the WebComponents that had firebase-query or firebase-document inside. During debugging I realized that the firebase properties of the child WebComponents were set before they were declared in the firebase-app element itself.

This is the order that worked for me:

<firebase-app
    name='someName'
    auth-domain="xxx.firebaseapp.com"
    database-url="xxx.firebaseio.com/"
    api-key="my-api-key">
</firebase-app>

And all the elements that use query or document should come only after this:

<some-component>
...
   <firebase-document
       app-name='someName'
       id="query"
       path="/app/firstName"
       data="{{testFirstName}}">
   </firebase-document> 
...
</some-component>