0
votes

I have the following simple data model in Firebase:

  • Partners
  • ----Name
  • ----OrigBal

This is the HTML:

<!DOCTYPE html>
<html ng-app="bastion">
<head>
    <title>Tester</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link href="css/bootstrap.min.css" rel="stylesheet" media="screen"/>
    <link rel="stylesheet" href="css/bastion.css"/>
</head>

<body ng-controller="PartnerCtrl">

    <table class="table edit">
        <thead>
            <tr>
                <th>Name</th>
                <th>Original Balance</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="(id, item) in items">
                <td><input type="text" ng-model="item.Name" ng-blur="updateItem(id)"/></td>
                <td><input type="text" ng-model="item.OrigBal" ng-blur="updateItem(id)"/></td>
                <td>
                    <a href="#" ng-click="removeItem(id)" class="navbar-link">Remove</a>
                </td>
            </tr>
        </tbody>
    </table>

    <div class="well">
        <h4>Add Item</h4>

        <form class="form-inline" role="form" ng-submit="addItem()" novalidate>
            <div class="form-group">
                <input type="text" class="form-control" ng-model="newItem.Name" placeholder="Name">
            </div>
            <div class="form-group">
                <input type="text" class="form-control" ng-model="newItem.OrigBal" placeholder="Original Balance">
            </div>
            <button type="submit" class="btn btn-default">Add</button>
        </form>
    </div>

    <script src="/Scripts/jquery-1.9.0.min.js"></script>
    <script src="/Scripts/bootstrap.min.js"></script>
    <script src="/Scripts/angular.min.js"></script>
    <script src="https://cdn.firebase.com/js/client/1.0.15/firebase.js"></script>
    <script src="/Scripts/angularfire.min.js"></script>


    <script src="/Scripts/bastion.js"></script>

</body>
</html>

And this is the Javascript:

var app = angular.module('bastion', ['firebase']);
app.constant('FIREBASE_URI', 'https://notpublic.firebaseio.com/Partners');

app.controller('PartnerCtrl', [
'$scope', 'PartnerService', function ($scope, PartnerService) {
    $scope.newItem = { Name: '', OrigBal: 0 };
    $scope.currentItem = null;

    $scope.items = PartnerService.getItems();

    $scope.addItem = function () {
        PartnerService.addItem(angular.copy($scope.newItem));
        $scope.newItem = { Name: '', OrigBal: 0 };
    };

    $scope.updateItem = function (id) {
        PartnerService.updateItem(id);
    };

    $scope.removeItem = function (id) {
        PartnerService.removeItem(id);
    };
}
]);

app.factory('PartnerService', [
'$firebase', 'FIREBASE_URI', function ($firebase, FIREBASE_URI) {
    var ref = new Firebase(FIREBASE_URI);
    var items = $firebase(ref);

    var getItems = function () {
        return items.$asObject();
    };

    var addItem = function (item) {
        items.$add(item);
    };

    var updateItem = function (id) {
        items.$save(id);
    };

    var removeItem = function (id) {
        items.$remove(id);
    };

    return {
        getItems: getItems,
        addItem: addItem,
        updateItem: updateItem,
        removeItem: removeItem
    }
}
]);

The removeItem() function works just fine, the getItems() works fine, but the addItem() and updateItem() both give the error: TypeError - undefined is not a function.

The proper values are being passed back to the PartnerService, but that is where the error occurs. I have tried rearranging the load order of the scripts, to no avail.

Is it possible that I need to include a promise with these functions in order to be sure all the data is present? I am at a bit of a loss at this point.

Thank you for any help you can give.

2
The version of AngularFire is 0.8, btw. - JesusReagan
Your items variable is set to $firebase. You want to call $save on the output of $asObject. Also, $add only exists on the synchronized array ($asArray), which is probably what you want to use anyway since you are working with a collection. - Kato
Thank you, Kato. In the Service, changing: var addItem = function(item) { getItems().$add(item); } and changing the getItems function to return items.$asArray() did the trick for me. - JesusReagan
Thanks again, @Kato. - JesusReagan

2 Answers

0
votes

I see you are using functions that are not on the $firebase(ref) object, you want to use it as $firebase(ref).$asArray(), see the Angularfire api

0
votes

Thanks again to @Kato. I had stopped short in coding the service and needed to actually use the function that returns all the records in order to modify the collection. Instead of this:

app.factory('PartnerService', [
'$firebase', 'FIREBASE_URI', function ($firebase, FIREBASE_URI) {
var ref = new Firebase(FIREBASE_URI);
var items = $firebase(ref);

var getItems = function () {
    return items.$asObject();
};

var addItem = function (item) {
    items.$add(item);
};

var updateItem = function (id) {
    items.$save(id);
};

var removeItem = function (id) {
    items.$remove(id);
};

return {
    getItems: getItems,
    addItem: addItem,
    updateItem: updateItem,
    removeItem: removeItem
}
}
]);

What I really needed is this:

app.factory('PartnerService', [
'$firebase', 'FIREBASE_URI', function ($firebase, FIREBASE_URI) {
var ref = new Firebase(FIREBASE_URI);
var items = $firebase(ref);

var getItems = function () {
    return items.$asArray();
};

var addItem = function (item) {
    getItems().$add(item);
};

var updateItem = function (id) {
    getItems().$save(id);
};

var removeItem = function (id) {
    getItems().$remove(id);
};

return {
    getItems: getItems,
    addItem: addItem,
    updateItem: updateItem,
    removeItem: removeItem
}
}
]);

Also thanks to @Anna Smother for noting that

return items.$asObject();

Should be

return items.$asArray();