hiroshi / knockoutFire

KnockoutFire.observable(firebase, map) WARNING: Abandoned
MIT License
29 stars 4 forks source link

EDIT: 2015-10-23: There is an alternative project.

https://github.com/CurtisHumphrey/knockout-firebase

EDIT: 2015-06-08: Status of the project and my opinion

I haven't use Firebase for a year or so. If I use Firebase for Javasecript front end work now, I think I choose React instead of Knockout. Sorry, but I mean I abandoned this project.

knockoutFire

KnockoutFire map Firebase json structure into HTML structure using KnockoutJs.

Live demo at jsFiddle.

How to use

Github pages as CDN

Latest release may have breaking changes.

I recommend to use versioned release, like 0.0.5 instead.

<script type="text/javascript" src="https://github.com/hiroshi/knockoutFire/raw/master//hiroshi.github.io/knockoutFire/knockoutfire-0.0.5.js"></script>

Also see CHANGELOG.

Using bower

In bower.json or component.json.

"dependencies": {
  ...
  "knockoutfire": "git://github.com/hiroshi/knockoutFire.git"
}

This will fetch latest tag.

Example

Firebase

items: {
  -XXX: {
    content: "Hello"
  }
  -YYY: {
    content: "World."
  }
}

HTML

<div id="viewModel">
  <ul data-bind="foreach: items">
    <li data-bind="text: content"></li>
  </ul>
</div>

Javascript

var firebase = new Firebase("https://knockoutFire-README-example.firebaseio-demo.com");
var viewModel = KnockoutFire.observable(firebase, {
  items: {
    "$item": {
      content: true,
    }
  }
});
ko.applyBindings(viewModel, document.getElementById("viewModel"));

API Reference

KnockoutFire.observable(firebaseRef, map)

The map option

The notation resembles to Firebase Security Rule.

Named propertiy

You need to specify which properties are used as observable properties of view models. KnockoutFire will retrieve only what specified in the map.

person: {
  firstName: true,
  lastName: true
}
$Variables and .reverse

If you use a property name start with $, the parent property will be ko.observableArray().

users: {
  "$user": {
    nickname: true,
  }
}

For add/remove/move operations, you should use Firebase API instead of manipulating observable array directly.

users()[1]().firebase.remove();

If you need reverse order;

comments: {
  ".reverse": true,
  "$comment": {
    content: true
  }
}
.startAt, .endAt, .limit
comments: {
  ".startAt": 0,
  ".endAt": {
    ".priority": 100,
    ".name": "foo"
  },
  ".limit": 20
}

For more information, Querying and Limiting Data in Firebase | Firebase Documentation.

.newItem and .priority

.newItem adds additional sub viewModel to an observable array.

comments: {
  ".newItem": true,
  "$comment": {
    content: true
  }
}
<div data-bind="with: comments.newItem">
  <form data-bind="submit: create">
    <input type="text" data-bind="value: content">
    <input type="submit">
  </form>
</div>

If you need a priority to be set;

".newItem": {
  ".priority": function() { return Date.now() }
}

If you need a default value rather than from a data-bind;

".newItem": {
  isdone: function(){ return false; }
}

If you need a callback on success;

".newItem": {
  ".on_success": function(){ do_someting(); }
}
.indexOf

To use Denormalized data use .indexOf.

members: {
  "$user": {
    ".indexOf": "/users/$user",
    "nickName": true
  }
}

You can access nickName like this:

members()[0]().nickName()
.extend

You can use Knockout extender.

ko.extenders.person = function(self, option) {
  self.fullName = ko.computed(function() {
    return this.firstName() + " " + this.lastName();
  });
};

Then specify the extender by name:

person: {
  firstName: true,
  lastName: true,
  ".extend": {person: true}
}