Monday, November 5, 2012

The Future of PlastronJS

It's been a little while since I wrote something about PlastronJS and although it isn't old I've had time to consider it's direction. There has been a lot of features added to the code recently and there is more coming, here are a few that are either in or looking to be put in the next month:

mvc.Layout

mvc.Control gives you some great functionality on top of goog.ui.Component as well as hooking up a model. But what if you want all that goodness without a model? Well now mvc.Layout inherits from goog.ui.Component and mvc.Control inherits now inherits from mvc.Layout. This means that you can use this.getEls, override addChild using this.placeChild_ and most importantly use the component level event system (this will be improved even more in the near future).

Dot property get/set/bind

In the same release as mvc.Layout comes dot property access. Ever wanted to listen to changes like this:

this.bind('address.country', function(country) {...});

You can even use get and set with dot property access, and all properties of an object that have changes below them will be enumerated:

a = new mvc.Model({'a': {'a': 1, 'b': 1}});
a.get('a.a'); // 1
a.bind('a', function() {alert('a');});
a.bind('a.a', function() {alert('a.a');});
a.bind('a.b', function() {alert('a.b');});
a.set('a.a', 2, true);
a.getChanges(); // ['a', 'a.a'];
a.change(); // alert a, alert a.a - but won't alert a.b

Also now any objects set will use a recursive check for changes by default.

One last handy thing is that this will even work with objects returned by computed properties.

Router ordering

Now the router will only run the first route that matches - also a route will not run when it's been added, you should run router.checkRoutes() when all routes have been added to fire the first time.

mvc.View

And now we move to the future. mvc.View will be an interface that much like that described in http://modernjavascript.blogspot.com/2012/06/v-in-mvc.html It will act almost like an mvc.Model where you can get and set and bind to changes. This means that the view itself will have an extra layer - or you could even use an mvc.Model as an mvc.View and bind two of them together with a control. I'll be providing some examples of how it could be used, but the possibilities are almost endless. One of the first implementations I will make will go through the DOM and use attributes on nodes to let the mvc.View know what data should be provided and how it should be interacted with (much like the in HTML binding clues given by Ender, Knockout or Angular). Another will be form based, and there will even be one that can aggregate views together. I'm hoping that I can show the flexibility and power of this idea in the near future.

mvc.Pool and filters/ordering

mvc.Collection is great but it is limited to only having one set of models and one sort order at a time. There will be a new model type soon that is a pool of models, like an unordered collection. What you can do beyond this is have something that inherits from mvc.Model and will have a filter and order that can be imposed on a pool that is passed to it. This means that if you have one set of models in a pool you can create two different order and give the pool to each, they will then both respond as if they were a collection but the pool will still manage it's own sync, only the filtering and sorting will be done by the object, the rest (like adding models) will be passed along to the pool. If you want to change sort order on a control you can do so by creating a new filter/sort, passing the pool in to that and setting the model of the control to the new filter/sort. Most likely mvc.Collection will actually become the filtering/sorting and if you instantiate it with models it will create a new mvc.Pool so that it is backwards compatible.

I'm planning to keep backwards compatibility with all these new features and improvements as well as going back over the code and improving it, so don't be afraid to dive in now and offer any suggestions as to what you'd like to see.


2 comments:

  1. I'd like to see a mechanism for getting a filtered collection from an existing collection that updated when the parent changed.

    var superCollection = new mvc.Collection();
    superCollection.add({type: "fruit", name: "apple"});
    superCollection.add({type: "fruit", name: "pear"});
    superCollection.add({type: "fruit", name: "kiwi"});
    superCollection.add({type: "vegetable", name: "carrot"});
    superCollection.add({type: "vegetable", name: "peas"});
    superCollection.add({type: "vegetable", name: "zucchini"});

    var subCollection = superCollection.filteredCollection(function(m) {
    return m.get('type') == "fruit";
    });

    assert subCollection.length() == 3;

    Feel free to use that as a test case btw ;-)

    Thanks for all your hard work! You have one of the most sensical libraries out there and it compiles down to be almost nothing in size. Love it!

    /** ~Andrew Allen */

    ReplyDelete
    Replies
    1. Yep, I've come across this situation before and that's the idea behind mvc.Pool which will just have the models and then you can pass that pool in to a filter and bind to the filter which should update when any of the pool's models update.

      There is a workaround that you can see if you look at the todomvc.com example:

      https://github.com/addyosmani/todomvc/blob/gh-pages/labs/architecture-examples/plastronjs/js/models/listmodel.js#L84

      here I changed the getModels (which the autolist function uses) that will return the getModels with the filter that I've saved on the model.

      https://github.com/addyosmani/todomvc/blob/gh-pages/labs/architecture-examples/plastronjs/js/controllers/listcontrol.js#L76

      Then here I've used autolist as usual but I've grabbed it's event object that is passed back and in particular the fire function from it which will cause the list to update. Then I just listen to any changes on a model or when I change my filter on the collection and tell it to update.

      I was thinking of having the filters and sort methods as different objects you can pass a pool in to, but I like your method better where a pool can return a new decorated object. I'll have a think about how I can best put that together, thanks!

      Delete