|
38 | 38 | * @constructor |
39 | 39 | */ |
40 | 40 | function FirebaseObject($firebase, destroyFn, readyPromise) { |
41 | | - var self = this; |
42 | | - |
43 | | - // These are private config props and functions used internally |
44 | | - // they are collected here to reduce clutter on the prototype |
45 | | - // and instance signatures. |
46 | | - self.$$conf = { |
| 41 | + // IDE does not understand defineProperty so declare traditionally |
| 42 | + // to avoid lots of IDE warnings about invalid properties |
| 43 | + this.$$conf = { |
47 | 44 | promise: readyPromise, |
48 | 45 | inst: $firebase, |
49 | 46 | bound: null, |
50 | 47 | destroyFn: destroyFn, |
51 | | - listeners: [], |
52 | | - /** |
53 | | - * Updates any bound scope variables and notifies listeners registered |
54 | | - * with $watch any time there is a change to data |
55 | | - */ |
56 | | - notify: function() { |
57 | | - if( self.$$conf.bound ) { |
58 | | - self.$$conf.bound.update(); |
59 | | - } |
60 | | - // be sure to do this after setting up data and init state |
61 | | - angular.forEach(self.$$conf.listeners, function (parts) { |
62 | | - parts[0].call(parts[1], {event: 'value', key: self.$id}); |
63 | | - }); |
64 | | - } |
| 48 | + listeners: [] |
65 | 49 | }; |
66 | 50 |
|
67 | | - self.$id = $firebase.$ref().ref().name(); |
68 | | - self.$priority = null; |
| 51 | + // this bit of magic makes $$conf non-enumerable and non-configurable |
| 52 | + // and non-writable (its properties are still writable but the ref cannot be replaced) |
| 53 | + Object.defineProperty(this, '$$conf', { |
| 54 | + value: this.$$conf |
| 55 | + }); |
| 56 | + |
| 57 | + this.$id = $firebase.$ref().ref().name(); |
| 58 | + this.$priority = null; |
| 59 | + |
| 60 | + $firebaseUtils.applyDefaults(this, this.$$defaults); |
69 | 61 | } |
70 | 62 |
|
71 | 63 | FirebaseObject.prototype = { |
|
74 | 66 | * @returns a promise which will resolve after the save is completed. |
75 | 67 | */ |
76 | 68 | $save: function () { |
77 | | - var notify = this.$$conf.notify; |
| 69 | + var notify = this.$$notify.bind(this); |
78 | 70 | return this.$inst().$set($firebaseUtils.toJSON(this)) |
79 | 71 | .then(function(ref) { |
80 | 72 | notify(); |
|
222 | 214 | $$updated: function (snap) { |
223 | 215 | // applies new data to this object |
224 | 216 | var changed = $firebaseUtils.updateRec(this, snap); |
| 217 | + $firebaseUtils.applyDefaults(this, this.$$defaults); |
225 | 218 | if( changed ) { |
226 | 219 | // notifies $watch listeners and |
227 | 220 | // updates $scope if bound to a variable |
228 | | - this.$$conf.notify(); |
| 221 | + this.$$notify(); |
229 | 222 | } |
230 | 223 | }, |
231 | 224 |
|
|
239 | 232 | $log.error(err); |
240 | 233 | // frees memory and cancels any remaining listeners |
241 | 234 | this.$destroy(err); |
| 235 | + }, |
| 236 | + |
| 237 | + /** |
| 238 | + * Updates any bound scope variables and notifies listeners registered |
| 239 | + * with $watch any time there is a change to data |
| 240 | + */ |
| 241 | + $$notify: function() { |
| 242 | + var self = this; |
| 243 | + if( self.$$conf.bound ) { |
| 244 | + self.$$conf.bound.update(); |
| 245 | + } |
| 246 | + // be sure to do this after setting up data and init state |
| 247 | + angular.forEach(self.$$conf.listeners, function (parts) { |
| 248 | + parts[0].call(parts[1], {event: 'value', key: self.$id}); |
| 249 | + }); |
| 250 | + }, |
| 251 | + |
| 252 | + /** |
| 253 | + * Overrides how Angular.forEach iterates records on this object so that only |
| 254 | + * fields stored in Firebase are part of the iteration. To include meta fields like |
| 255 | + * $id and $priority in the iteration, utilize for(key in obj) instead. |
| 256 | + */ |
| 257 | + forEach: function(iterator, context) { |
| 258 | + return $firebaseUtils.each(this, iterator, context); |
242 | 259 | } |
243 | 260 | }; |
244 | 261 |
|
|
0 commit comments