4
votes

I have an AngularFire object ($firebaseObject()) named ctrl.data, which ng-repeat displays. In the markup generated by ng-repeat I have a button which runs a function when clicked. I would like to pass information from the item that ng-repeat used to fill out the markup to a function.

My data on Firebase is structured as such*:

enter image description here *all spaces have been removed from object names

Markup

<div ng-repeat="data in ctrl.data track by $index">
    {{data.name}}, {{data.lvl}} ...
    <input type="button" ng-click="ctrl.addToBook(data.classes, data.comp, data.csttime, ...)" value="Add!">
</div>

The function

ctrl.addToBook = function (classes, comp, csttime, ...) {
      ctrl.book.push({
        classes: classes, comp: comp, csttime: csttime ...
      });

When the function runs it is pushing:

{classes: undefined, comp: undefined, csttime: undefined...}

I've also tried

  • Replacing passing the argument data and pushing the entire object but I'm told what I'm pushing is undefined. Example: ng-click="addToBook(data)" and function(toBePassed) {data.book.push(toBePassed);}
  • Putting {{ }} around each argument, which Angular didn't want render. Error: [$parse:syntax] http://errors.angularjs.org/1.3.15/$parse/syntax?... Later it references to the button. Following the link gives: Error: $parse:syntax / Syntax Error: Syntax Error: Token '' {1} at column {2} of the expression [{3}] starting at [{4}]. Which I don't know how to interpret.

What do I need to do to pass the information to the function, or have the function know what to push?

Each object that is being iterated by ng-repeat has a name property which matches the name of the object, so the name of the objects could be removed and I could use an array instead of an object. Would restructuring the data so it's an array make this easier, because I could then reference to an Id? If so I believe I would be in a similar situation to this, but would prefer to avoid using Id's.

Another alternative would be giving each object a method which pushes the needed data. Would this be a better approach? I'm still feeling rather new to angular but I think angular.forEach and $firebaseObject.$extend would be where to start, is that correct?


More information:

I've double checked the contents of ctrl.data. Each entry has data.__.classes, so I don't think the issue is from missing parameters. This is console.log(ctrl.data)'s output.

$$conf: Object
$id: null
$priority: null
AnimalFriendship: Object
    classes: "Bard, Cleric (Nature), Druid, Ranger"
    comp: "V, S, M (a morsel of food)"
    csttime: "1 action"
    desc: "-Long description-"
    duration: "24 hours"
    lvl: 1
    name: "Animal Friendship"
    range: "30 feet"
    ritual: false
    school: "Enchantment"
    __proto__: Object
-Many more objects which have the same properties as above-
__proto__: Object
    $$error: ...
    $$notify: ...
    $bindTo: ...
    $destroy: ...
    $loaded: ...
    $ref: ...
    $remove: ...
    $save: ...
    $watch: ...
    forEach: ...
    __proto__: Object

However console.log(ctrl.data.AnimalFriendship) outputs undefined.


tldr; I'm unable to access the objects which ng-repeat are accessing, and therefore cannot pass the information that each iteration is dealing with into a function. Changing from an AngularFire Object to AngularFire Array may need to be the answer, and careful planning to avoid possible $index problems.

2
If this is still a problem, put up a plunkr which shows the problem and I'll take a look at it - Rachel

2 Answers

0
votes

It seems that data does not have the required parameters - so data.classes etc are undefined. The object data itself is defined though; if it wasn't, an error would be thrown earlier on. Try double checking what you're iterating over (ie. ctrl.data) and if the object of the iteration actually has the parameters you are looking for.

0
votes

Without seeing your controller code (assuming it's named 'ctrl'?), I can't say for sure, but I think you're looking for

$scope.addToBook = function (...) {
    ...
};

And then call your method like so: ng-click="addToBook..."

You should be setting your data on $scope as well, so $scope.data = []

Then it would be referenced as just data, not ctrl.data in the mark-up.