I recently started learning AngularJS+Firebase. I'm trying to write in my firebase an object like this:
{
title: "Personal Information",
say: [
[{ "eng": "What's", "ukr": "Що є" }, { "eng": "your", "ukr": "твоє" }, { "eng": "surname?", "ukr": "прізвище?" }],
[{ "eng": "Smith", "ukr": "Сміт" }],
[{ "eng": "What's", "ukr": "Що є" }, { "eng": "your", "ukr": "твоє" }, { "eng": "first", "ukr": "перше" }, { "eng": "name?", "ukr": "ім'я?(не фамілія)" }]
]
}
with line:
lessondata.add($scope.topic);
where 'lessondata' is service created with angularFireCollection() and $scope.topic - object bound to my UI. But got the following error: Firebase.push failed: first argument contains an invalid key ($$hashKey) in property 'say.0.0'. Keys must be non-empty strings and can't contain ".", "#", "$", "/", "[", or "]"
As I understood Firebase do not allow to use 0 as a key even if it's a key in an attached array for which zero key is natural. So should I change my object structure in some hardcoded instance or I miss something? Thanks in advance!
EDIT: As Anant points out in the comments, in the latest stable version of Angular (1.0.7 atm), you can use angular.copy(obj)
to remove $$hashkey
attributes.
Like Michael said, the '$' in '$$hashKey' is the issue. Angular creates the $$hashKey
properties behind the scenes (see more here: https://groups.google.com/forum/#!topic/angular/pI0IgNHKjxw). I've gotten around this issue by doing something like myRef.push(angular.fromJson(angular.toJson(myAngularObject)))
.
The issue is the $ in "$$hashKey", not the 0. 0 is allowed.
I wanted to throw another answer in here that is much simpler, just use track by
in your repeat. It will get rid of the $$hashKey
attribute that is causing so much grief.
<div ng-repeat="item in items track by $index">{{item.name}}</div>
I'm a bit late to this but I thought I would like to add my two cents as I was shaking my head to all the other answers. Hopefully this can help you to avoid this issue all together.
Use the angularFire library intended to handle angular data and use it's methods.
while yes you can use the pure javascript library methods to .push() .add() .update()
, .set()
ect.
So if you want to avoid any clashes when firebase communicates with angular javascript you need to be using the appropriate .$foo()
methods (i.e. .$save()
). In your case just add the $
to your .add()
(make it .$add()
)
so use lessondata.$add($scope.topic);
differences when saving with firebase's vs angularfire's
AngularFire's $save()
method is implemented using Firebase's set()
method.
Firebase's push()
operation corresponds to AngularFire's $add()
method
Typically you should be using set()/$save() if you either have an object that already exists in the database or if you are working with objects that have a natural key. more info on that here: https://stackoverflow.com/a/35959496/4642530
Things to note with AngularFire
For a callback:
and if you want a callback to know if your data saved correctly you can do something like this:
var list = $firebaseArray(ref);
list.$add({ foo: "bar" }).then(function(ref) {
var id = ref.key();
console.log("added record with id " + id);
list.$indexFor(id); // returns location in the array
});
I was surprised this wasn't mentioned earlier in any of the other answers, but take a look at these docs https://www.firebase.com/docs/web/libraries/angular/api.html#angularfire-firebasearray-addnewdata
Cheers.
The best way to get rid of the $$hasKeys is to use "track by" in ng-repeats as in the following (as mentioned in the answer above)
<div ng-repeat="(key, value) in myObj track by $index"> ... </div>
but you can also set track as par of ng-model-options
ng-model-options="{ trackBy: '$value.someKeyOnYourObject' }"
on a form control. This way also improves performance of your angular app.
Another way is to remove the $$hashKey is using
angular.copy(someObj);
If all else fails, you could also use lodash to remove the keys that start with the "$".
_.omitBy(yourObject, function(value, key){return _.startsWith(key, '$');});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With