Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Commit

Permalink
#8 Pass Query to Firebase ref
Browse files Browse the repository at this point in the history
  • Loading branch information
EddyVerbruggen committed Jan 30, 2016
1 parent da7818c commit 6258122
Show file tree
Hide file tree
Showing 5 changed files with 257 additions and 45 deletions.
53 changes: 50 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ NativeScript 1.3.0 (`tns --version`) is required for smooth installation, so ple

Head on over to firebase.com and sign up for a free account.
Your first 'Firebase' will be automatically created and made available via a URL
like https://resplendent-fire-4211.firebaseio.com/.
like `https://resplendent-fire-4211.firebaseio.com/`.

## Installation
From the command prompt go to your app's root folder and execute:
Expand Down Expand Up @@ -69,8 +69,8 @@ The plugin will take care of serializing JSON data to native data structures.
firebase.setValue(
'/companies',
[
{name: 'Telerik'},
{name: 'Google'}
{name: 'Telerik', country: 'Bulgaria'},
{name: 'Google', country: 'USA'}
]
);
```
Expand All @@ -94,6 +94,49 @@ This function will store a JSON object at path `<Firebase URL>/users/<Generated
);
```

### query
Firebase supports querying data and this plugin does too, since v2.0.0.

Let's say we have the structure as defined at `setValue`, then use this query to retrieve the companies in country 'Bulgaria':

```js
var onQueryEvent = function(result) {
// note that the query returns 1 match at a time
// in the order specified in the query
if (!result.error) {
console.log("Event type: " + result.type);
console.log("Key: " + result.key);
console.log("Value: " + JSON.stringify(result.value));
}
};

firebase.query(
onQueryEvent,
"/companies",
{
// order by company.country
orderBy: {
type: firebase.QueryOrderByType.CHILD,
value: 'country' // mandatory when type is 'child'
},
// but only companies named 'Telerik'
// (this range relates to the orderBy clause)
range: {
type: firebase.QueryRangeType.EQUAL_TO,
value: 'Bulgaria'
},
// only the first 2 matches
// (note that there's only 1 in this case anyway)
limit: {
type: firebase.QueryLimitType.LAST,
value: 2
}
}
);
```

For supported values of the orderBy/range/limit's `type` properties, take a look at the [`firebase-common.d.ts`](firebase-common.d.ts) TypeScript definitions in this repo.

### addChildEventListener
To listen for changes in your database you can pass in a listener callback function.
You get to control which path inside you database you want to listen to, by default it's `/` which is the entire database.
Expand Down Expand Up @@ -218,6 +261,10 @@ The Firebase Dashboard can be reached by simply loading your Firebase URL in a w

or start a geny emulator first and do: `tns run android`

## Future work
- Add support for `removeEventListener`.
- Possibly add more login mechanisms.


## Credits
The starting point for this plugin was [this great Gist](https://gist.github.com/jbristowe/c89a7bcae7fc9a035ee7) by [John Bristowe](https://github.com/jbristowe).
20 changes: 19 additions & 1 deletion firebase-common.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
var firebase = {};

firebase.loginType = {
firebase.LoginType = {
ANONYMOUS: "anonymous",
PASSWORD: "password"
};

firebase.QueryOrderByType = {
KEY: "key",
VALUE: "value",
CHILD: "child",
PRIORITY: "priority"
};

firebase.QueryLimitType = {
FIRST: "first",
LAST: "last"
};

firebase.QueryRangeType = {
START_AT: "startAt",
END_AT: "endAt",
EQUAL_TO: "equalTo"
};

firebase.instance = null;

// this implementation is actually the same for both platforms, woohoo :)
Expand Down
115 changes: 92 additions & 23 deletions firebase.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ firebase.toHashMap = function(obj) {
var node = new java.util.HashMap();
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (obj[property] != null) {
if (obj[property] !== null) {
switch (typeof obj[property]) {
case 'object':
node.put(property, firebase.toHashMap(obj[property], node));
Expand All @@ -30,19 +30,17 @@ firebase.toHashMap = function(obj) {
};

firebase.toJsObject = function(javaObj) {
if (javaObj == null || typeof javaObj != "object") {
if (javaObj === null || typeof javaObj != "object") {
return javaObj;
}

var node;
switch (javaObj.getClass().getName()) {
case 'java.lang.Boolean':
return Boolean(String(javaObj));
break;
case 'java.lang.Long':
case 'java.lang.Double':
return Number(String(javaObj));
break;
case 'java.util.ArrayList':
node = [];
for (var i = 0; i < javaObj.size(); i++) {
Expand All @@ -53,7 +51,7 @@ firebase.toJsObject = function(javaObj) {
node = {};
var iterator = javaObj.entrySet().iterator();
while (iterator.hasNext()) {
item = iterator.next();
var item = iterator.next();
switch (item.getClass().getName()) {
case 'java.util.HashMap$HashMapEntry':
node[item.getKey()] = firebase.toJsObject(item.getValue());
Expand Down Expand Up @@ -81,7 +79,7 @@ firebase.getCallbackData = function(type, snapshot) {
type: type,
key: snapshot.getKey(),
value: firebase.toJsObject(snapshot.getValue())
}
};
};

firebase.init = function (arg) {
Expand Down Expand Up @@ -117,9 +115,10 @@ firebase.login = function (arg) {
});

var type = arg.type;
if (type === firebase.loginType.ANONYMOUS) {

if (type === firebase.LoginType.ANONYMOUS) {
instance.authAnonymously(authorizer);
} else if (type === firebase.loginType.PASSWORD) {
} else if (type === firebase.LoginType.PASSWORD) {
if (!arg.email || !arg.password) {
reject("Auth type emailandpassword requires an email and password argument");
} else {
Expand Down Expand Up @@ -160,24 +159,28 @@ firebase.createUser = function (arg) {
});
};

firebase._addObservers = function(to, updateCallback) {
var listener = new com.firebase.client.ChildEventListener({
onChildAdded: function (snapshot, previousChildKey) {
updateCallback(firebase.getCallbackData('ChildAdded', snapshot));
},
onChildRemoved: function (snapshot) {
updateCallback(firebase.getCallbackData('ChildRemoved', snapshot));
},
onChildChanged: function (snapshot, previousChildKey) {
updateCallback(firebase.getCallbackData('ChildChanged', snapshot));
},
onChildMoved: function (snapshot, previousChildKey) {
updateCallback(firebase.getCallbackData('ChildMoved', snapshot));
}
});
to.addChildEventListener(listener);
};

firebase.addChildEventListener = function (updateCallback, path) {
return new Promise(function (resolve, reject) {
try {
var listener = new com.firebase.client.ChildEventListener({
onChildAdded: function (snapshot, previousChildKey) {
updateCallback(firebase.getCallbackData('ChildAdded', snapshot));
},
onChildRemoved: function (snapshot) {
updateCallback(firebase.getCallbackData('ChildRemoved', snapshot));
},
onChildChanged: function (snapshot, previousChildKey) {
updateCallback(firebase.getCallbackData('ChildChanged', snapshot));
},
onChildMoved: function (snapshot, previousChildKey) {
updateCallback(firebase.getCallbackData('ChildMoved', snapshot));
}
});
instance.child(path).addChildEventListener(listener);
firebase._addObservers(instance.child(path), updateCallback);
resolve();
} catch (ex) {
console.log("Error in firebase.addChildEventListener: " + ex);
Expand Down Expand Up @@ -245,6 +248,72 @@ firebase.setValue = function (path, val) {
});
};

firebase.query = function (updateCallback, path, options) {
return new Promise(function (resolve, reject) {
try {
var query;

// orderBy
if (options.orderBy.type === firebase.QueryOrderByType.KEY) {
query = instance.child(path).orderByKey();
} else if (options.orderBy.type === firebase.QueryOrderByType.VALUE) {
query = instance.child(path).orderByValue();
} else if (options.orderBy.type === firebase.QueryOrderByType.PRIORITY) {
query = instance.child(path).orderByPriority();
} else if (options.orderBy.type === firebase.QueryOrderByType.CHILD) {
if (!options.orderBy.value) {
reject("When orderBy.type is 'child' you must set orderBy.value as well.");
return;
}
query = instance.child(path).orderByChild(options.orderBy.value);
} else {
reject("Invalid orderBy.type, use constants like firebase.QueryOrderByType.VALUE");
return;
}

// range
if (options.range && options.range.type) {
if (!options.range.value) {
reject("Please set range.value");
return;
}
if (options.range.type === firebase.QueryRangeType.START_AT) {
query = query.startAt(options.range.value);
} else if (options.range.type === firebase.QueryRangeType.END_AT) {
query = query.endAt(options.range.value);
} else if (options.range.type === firebase.QueryRangeType.EQUAL_TO) {
query = query.equalTo(options.range.value);
} else {
reject("Invalid range.type, use constants like firebase.QueryRangeType.START_AT");
return;
}
}

// limit
if (options.limit && options.limit.type) {
if (!options.limit.value) {
reject("Please set limit.value");
return;
}
if (options.limit.type === firebase.QueryLimitType.FIRST) {
query = query.limitToFirst(options.limit.value);
} else if (options.limit.type === firebase.QueryLimitType.LAST) {
query = query.limitToLast(options.limit.value);
} else {
reject("Invalid limit.type, use constants like firebase.QueryLimitType.FIRST");
return;
}
}

firebase._addObservers(query, updateCallback);
resolve();
} catch (ex) {
console.log("Error in firebase.query: " + ex);
reject(ex);
}
});
};

firebase.remove = function (path) {
return new Promise(function (resolve, reject) {
try {
Expand Down
Loading

0 comments on commit 6258122

Please sign in to comment.