Search code examples
firebasepolymerpolymer-1.0geofire

Geofire query events not firing


I am making a Polymer web component for using Geofire's queries. I am using them in a separate app successfully (using js), but while testing the component, the query is not firing any events. The Firebase db does contain data.

Below is the relevant code, and here is the demo.

geofire-query.html

<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="scripts.html">
<link rel="import" href="geofire-elements-behavior.html">

<!--
`geofire-query`
An element for working with GeoFire's [`GeoQuery`](https://github.com/firebase/geofire-js/blob/master/docs/reference.md#geoquery)s.
@polymerBehavior GeofireElementsBehavior
@demo demo/index.html
-->

<dom-module id="geofire-query">
  <template>
    <style>
      :host {
        /*display: block;*/
      }
    </style>
  </template>

  <script>
    Polymer({
      is: 'geofire-query',
      properties: {
        /**
         * The latitude for the query's center.
         */
        lat: Number,
        /**
         * The longitude for the query's center.
         */
        lng: Number,
        /**
         * The radius in kilometers around the query's center.
         */
        radius: Number,
        /**
         * Whether the query is active and listening for GeoQuery events.
         */
        idle: {
          type: Boolean,
          value: false,
          reflectToAttribute: true,
//          observer: '_idleChanged'
        },
        /**
         * An array managed by the GeoQuery events.
         * Each element is an object with properties `key, lat, lng, location, distance`.
         */
        resultsArray: {
          type: Array,
          notify: true
        },
        /**
         * An object managed by the GeoQuery events.
         * It is a map of key => {`lat, lng, location, distance`}.
         */
        resultsObject: {
          type: Object,
          notify: true
        }
      },
      observers: [
        '_idleChanged(idle, _query)',
        '_queryChanged(lat, lng, radius)'
      ],
      behaviors: [
         GeofireElementsBehavior
      ],
      _idleChanged: function(idle, query) {
        if (!query) return;
        console.log('we have a query', query.center(), query.radius(), idle, query, 'app=', this.app);
        if (!idle) {
          this.resultsArray = [];
          this.resultsObject = {};
          console.log('setting listeners...');
          this.onKeyEnteredRegistration = query.on('key_entered', function(key, location, distance) {
            console.log('key-entered', key, location, distance);
            this.resultsObject[key] = {
              lat: location[0],
              lng: location[1],
              location: location,
              distance: distance
            };
            var data = {
              key: key,
              lat: location[0],
              lng: location[1],
              location: location,
              distance: distance
            };
            this.resultsArray.push(data);
            this.fire('key-entered', data);
          }.bind(this));
          this.onKeyExitedRegistration = query.on("key_exited", function(key, location, distance) {
            this.resultsObject[key] = null;
            for (var i = 0; i < this.resultsArray.length; i++) {
              if (this.resultsArray[i].key == key) {
                this.resultsArray.splice(i, 1);
                break;
              }
            }
            this.fire('key-exited', {
              key: key,
              lat: location[0],
              lng: location[1],
              location: location,
              distance: distance
            });
          }.bind(this));
          this.onKeyMovedRegistration = query.on("key_moved", function(key, location, distance) {
            this.resultsObject[key] = {
              lat: location[0],
              lng: location[1],
              location: location,
              distance: distance
            };
            var data = {
              key: key,
              lat: location[0],
              lng: location[1],
              location: location,
              distance: distance
            };
            for (var i = 0; i < this.resultsArray.length; i++) {
              if (this.resultsArray[i].key == key) {
                this.resultsArray[i] = data;
                break;
              }
            }
            this.fire('key-moved', data);
          }.bind(this));
          this.onReadyRegistration = query.on("ready", function() {
            console.log('ready');
            this.fire('ready');
          }.bind(this));
        } else {
          query.cancel();
          query = null;
          console.log('set query to null?', this._query === null);
        }
      },
      _queryChanged: function(lat, lng, radius) {
        if ((lat || lat === 0) && (lng || lng === 0) && radius) {
          console.log('querying [', lat, lng, ']', radius, 'km');
          var criteria = {
            center: [lat, lng],
            radius: radius
          };
          if (this._query) {
            this._query.updateCriteria(criteria);
          } else {
            this._query = this._geofire.query(criteria);
          }
        }
      }
      /**
       * Corresponds to the GeoQuery's `key_entered` event. Fires after updating the internal results.
       * @event key-entered
       * @param {key} string The location's identifier.
       * @param {lat} number Latitude.
       * @param {lng} number Longitude.
       * @param {location} array [lat, lng] shorthand.
       * @param {distance} number Distance from the query's center, in kilometers.
       */
      /**
       * Corresponds to the GeoQuery's `key_exited` event. Fires after updating the internal results.
       * @event key-exited
       * @param {key} string The location's identifier.
       * @param {lat} number Latitude.
       * @param {lng} number Longitude.
       * @param {location} array [lat, lng].
       * @param {distance} number Distance from the query's center, in kilometers.
       */
      /**
       * Corresponds to the GeoQuery's `key_moved` event. Fires after updating the internal results.
       * @event key-moved
       * @param {key} string The location's identifier.
       * @param {lat} number Latitude.
       * @param {lng} number Longitude.
       * @param {location} array [lat, lng].
       * @param {distance} number Distance from the query's center, in kilometers.
       */
      /**
       * Corresponds to the GeoQuery's `ready` event. Fired when the initial result set of the query is ready.
       * @event ready
       */
    });
  </script>
</dom-module>

geofire-elements-behavior.html

<script>
/**
 * @polymerBehavior
 */
 GeofireElementsBehavior = {
        properties: {
          /**
           * The Firebase app's name. If not specified, the default Firebase app will be used.
           */
          app: String,
          /**
           * The path to this geofire's data inside the Firebase database.
           */
          path: String
        },
        // observers: [
        //   '_geofireChanged(app, path)'
        // ],
        //
        // _geofireChanged: function(app, path) {
        //   this._geofire = new GeoFire(firebase.app(app).database().ref(path));
        // },
        /**
         * The [GeoFire](https://github.com/firebase/geofire-js/blob/master/docs/reference.md#geofire) instance.
         */
        get _geofire() {
            if (!this.geofireInstance) {
                console.log('init geofire. app=', this.app, 'path=', this.path);
                this.geofireInstance = new GeoFire(firebase.app(this.app).database().ref(this.path));
            }
            return this.geofireInstance;
        }
    };
</script>

Solution

  • It was a silly rules mistake :(

    I had

    {
      "rules": {
        "geofire1": {
          "$key": {    
            ".read": "true",    
            ".write": "true"
          }
        }
      }
    }
    

    But I needed

    {
      "rules": {
        "geofire1": {
          ".read": "true",
          ".indexOn": "g",
          "$key": {        
            ".write": "true"
          }
        }
      }
    }