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

Commit 6258122

Browse files
#8 Pass Query to Firebase ref
1 parent da7818c commit 6258122

File tree

5 files changed

+257
-45
lines changed

5 files changed

+257
-45
lines changed

README.md

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ NativeScript 1.3.0 (`tns --version`) is required for smooth installation, so ple
1919

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

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

97+
### query
98+
Firebase supports querying data and this plugin does too, since v2.0.0.
99+
100+
Let's say we have the structure as defined at `setValue`, then use this query to retrieve the companies in country 'Bulgaria':
101+
102+
```js
103+
var onQueryEvent = function(result) {
104+
// note that the query returns 1 match at a time
105+
// in the order specified in the query
106+
if (!result.error) {
107+
console.log("Event type: " + result.type);
108+
console.log("Key: " + result.key);
109+
console.log("Value: " + JSON.stringify(result.value));
110+
}
111+
};
112+
113+
firebase.query(
114+
onQueryEvent,
115+
"/companies",
116+
{
117+
// order by company.country
118+
orderBy: {
119+
type: firebase.QueryOrderByType.CHILD,
120+
value: 'country' // mandatory when type is 'child'
121+
},
122+
// but only companies named 'Telerik'
123+
// (this range relates to the orderBy clause)
124+
range: {
125+
type: firebase.QueryRangeType.EQUAL_TO,
126+
value: 'Bulgaria'
127+
},
128+
// only the first 2 matches
129+
// (note that there's only 1 in this case anyway)
130+
limit: {
131+
type: firebase.QueryLimitType.LAST,
132+
value: 2
133+
}
134+
}
135+
);
136+
```
137+
138+
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.
139+
97140
### addChildEventListener
98141
To listen for changes in your database you can pass in a listener callback function.
99142
You get to control which path inside you database you want to listen to, by default it's `/` which is the entire database.
@@ -218,6 +261,10 @@ The Firebase Dashboard can be reached by simply loading your Firebase URL in a w
218261

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

264+
## Future work
265+
- Add support for `removeEventListener`.
266+
- Possibly add more login mechanisms.
267+
221268

222269
## Credits
223270
The starting point for this plugin was [this great Gist](https://gist.github.com/jbristowe/c89a7bcae7fc9a035ee7) by [John Bristowe](https://github.com/jbristowe).

firebase-common.js

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,28 @@
11
var firebase = {};
22

3-
firebase.loginType = {
3+
firebase.LoginType = {
44
ANONYMOUS: "anonymous",
55
PASSWORD: "password"
66
};
77

8+
firebase.QueryOrderByType = {
9+
KEY: "key",
10+
VALUE: "value",
11+
CHILD: "child",
12+
PRIORITY: "priority"
13+
};
14+
15+
firebase.QueryLimitType = {
16+
FIRST: "first",
17+
LAST: "last"
18+
};
19+
20+
firebase.QueryRangeType = {
21+
START_AT: "startAt",
22+
END_AT: "endAt",
23+
EQUAL_TO: "equalTo"
24+
};
25+
826
firebase.instance = null;
927

1028
// this implementation is actually the same for both platforms, woohoo :)

firebase.android.js

Lines changed: 92 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ firebase.toHashMap = function(obj) {
55
var node = new java.util.HashMap();
66
for (var property in obj) {
77
if (obj.hasOwnProperty(property)) {
8-
if (obj[property] != null) {
8+
if (obj[property] !== null) {
99
switch (typeof obj[property]) {
1010
case 'object':
1111
node.put(property, firebase.toHashMap(obj[property], node));
@@ -30,19 +30,17 @@ firebase.toHashMap = function(obj) {
3030
};
3131

3232
firebase.toJsObject = function(javaObj) {
33-
if (javaObj == null || typeof javaObj != "object") {
33+
if (javaObj === null || typeof javaObj != "object") {
3434
return javaObj;
3535
}
3636

3737
var node;
3838
switch (javaObj.getClass().getName()) {
3939
case 'java.lang.Boolean':
4040
return Boolean(String(javaObj));
41-
break;
4241
case 'java.lang.Long':
4342
case 'java.lang.Double':
4443
return Number(String(javaObj));
45-
break;
4644
case 'java.util.ArrayList':
4745
node = [];
4846
for (var i = 0; i < javaObj.size(); i++) {
@@ -53,7 +51,7 @@ firebase.toJsObject = function(javaObj) {
5351
node = {};
5452
var iterator = javaObj.entrySet().iterator();
5553
while (iterator.hasNext()) {
56-
item = iterator.next();
54+
var item = iterator.next();
5755
switch (item.getClass().getName()) {
5856
case 'java.util.HashMap$HashMapEntry':
5957
node[item.getKey()] = firebase.toJsObject(item.getValue());
@@ -81,7 +79,7 @@ firebase.getCallbackData = function(type, snapshot) {
8179
type: type,
8280
key: snapshot.getKey(),
8381
value: firebase.toJsObject(snapshot.getValue())
84-
}
82+
};
8583
};
8684

8785
firebase.init = function (arg) {
@@ -117,9 +115,10 @@ firebase.login = function (arg) {
117115
});
118116

119117
var type = arg.type;
120-
if (type === firebase.loginType.ANONYMOUS) {
118+
119+
if (type === firebase.LoginType.ANONYMOUS) {
121120
instance.authAnonymously(authorizer);
122-
} else if (type === firebase.loginType.PASSWORD) {
121+
} else if (type === firebase.LoginType.PASSWORD) {
123122
if (!arg.email || !arg.password) {
124123
reject("Auth type emailandpassword requires an email and password argument");
125124
} else {
@@ -160,24 +159,28 @@ firebase.createUser = function (arg) {
160159
});
161160
};
162161

162+
firebase._addObservers = function(to, updateCallback) {
163+
var listener = new com.firebase.client.ChildEventListener({
164+
onChildAdded: function (snapshot, previousChildKey) {
165+
updateCallback(firebase.getCallbackData('ChildAdded', snapshot));
166+
},
167+
onChildRemoved: function (snapshot) {
168+
updateCallback(firebase.getCallbackData('ChildRemoved', snapshot));
169+
},
170+
onChildChanged: function (snapshot, previousChildKey) {
171+
updateCallback(firebase.getCallbackData('ChildChanged', snapshot));
172+
},
173+
onChildMoved: function (snapshot, previousChildKey) {
174+
updateCallback(firebase.getCallbackData('ChildMoved', snapshot));
175+
}
176+
});
177+
to.addChildEventListener(listener);
178+
};
179+
163180
firebase.addChildEventListener = function (updateCallback, path) {
164181
return new Promise(function (resolve, reject) {
165182
try {
166-
var listener = new com.firebase.client.ChildEventListener({
167-
onChildAdded: function (snapshot, previousChildKey) {
168-
updateCallback(firebase.getCallbackData('ChildAdded', snapshot));
169-
},
170-
onChildRemoved: function (snapshot) {
171-
updateCallback(firebase.getCallbackData('ChildRemoved', snapshot));
172-
},
173-
onChildChanged: function (snapshot, previousChildKey) {
174-
updateCallback(firebase.getCallbackData('ChildChanged', snapshot));
175-
},
176-
onChildMoved: function (snapshot, previousChildKey) {
177-
updateCallback(firebase.getCallbackData('ChildMoved', snapshot));
178-
}
179-
});
180-
instance.child(path).addChildEventListener(listener);
183+
firebase._addObservers(instance.child(path), updateCallback);
181184
resolve();
182185
} catch (ex) {
183186
console.log("Error in firebase.addChildEventListener: " + ex);
@@ -245,6 +248,72 @@ firebase.setValue = function (path, val) {
245248
});
246249
};
247250

251+
firebase.query = function (updateCallback, path, options) {
252+
return new Promise(function (resolve, reject) {
253+
try {
254+
var query;
255+
256+
// orderBy
257+
if (options.orderBy.type === firebase.QueryOrderByType.KEY) {
258+
query = instance.child(path).orderByKey();
259+
} else if (options.orderBy.type === firebase.QueryOrderByType.VALUE) {
260+
query = instance.child(path).orderByValue();
261+
} else if (options.orderBy.type === firebase.QueryOrderByType.PRIORITY) {
262+
query = instance.child(path).orderByPriority();
263+
} else if (options.orderBy.type === firebase.QueryOrderByType.CHILD) {
264+
if (!options.orderBy.value) {
265+
reject("When orderBy.type is 'child' you must set orderBy.value as well.");
266+
return;
267+
}
268+
query = instance.child(path).orderByChild(options.orderBy.value);
269+
} else {
270+
reject("Invalid orderBy.type, use constants like firebase.QueryOrderByType.VALUE");
271+
return;
272+
}
273+
274+
// range
275+
if (options.range && options.range.type) {
276+
if (!options.range.value) {
277+
reject("Please set range.value");
278+
return;
279+
}
280+
if (options.range.type === firebase.QueryRangeType.START_AT) {
281+
query = query.startAt(options.range.value);
282+
} else if (options.range.type === firebase.QueryRangeType.END_AT) {
283+
query = query.endAt(options.range.value);
284+
} else if (options.range.type === firebase.QueryRangeType.EQUAL_TO) {
285+
query = query.equalTo(options.range.value);
286+
} else {
287+
reject("Invalid range.type, use constants like firebase.QueryRangeType.START_AT");
288+
return;
289+
}
290+
}
291+
292+
// limit
293+
if (options.limit && options.limit.type) {
294+
if (!options.limit.value) {
295+
reject("Please set limit.value");
296+
return;
297+
}
298+
if (options.limit.type === firebase.QueryLimitType.FIRST) {
299+
query = query.limitToFirst(options.limit.value);
300+
} else if (options.limit.type === firebase.QueryLimitType.LAST) {
301+
query = query.limitToLast(options.limit.value);
302+
} else {
303+
reject("Invalid limit.type, use constants like firebase.QueryLimitType.FIRST");
304+
return;
305+
}
306+
}
307+
308+
firebase._addObservers(query, updateCallback);
309+
resolve();
310+
} catch (ex) {
311+
console.log("Error in firebase.query: " + ex);
312+
reject(ex);
313+
}
314+
});
315+
};
316+
248317
firebase.remove = function (path) {
249318
return new Promise(function (resolve, reject) {
250319
try {

0 commit comments

Comments
 (0)