mikeric / rivets

Lightweight and powerful data binding.
http://rivetsjs.com
MIT License
3.23k stars 310 forks source link

declarative binding from code #458

Open cybernetlab opened 9 years ago

cybernetlab commented 9 years ago

Hi! I adopting rivets to use it with Backbone and Marionette. And I want to provide a way to make bindings from code in class declarations like this:

var View = Marionette.ItemView.extend({
  rivets: {
    '.some-class': 'text user.name',
    'input[name="interests"]': 'value user.interests'
  }
});

that would be equivalent to following markup:

<div>
  <div class="some-class" rv-text="user.name"></div>
  <input type="text" name="interests" rv-value="user.interests"/>
</div>

After some digging in your code I've wrote binding function for this purpose (with some simplification) that is called from Marionette onRender event:

// called in Marionette View context
var bindRivets = function() {
  // firstly bind via markup as usual
  var binding = this.binding = rivets.bind(this.el, this.model);
  // and then add some bindings from code
  _.each(this.rivets, function(rivet, selector) {
    // split into type and declaration parts
    rivet = rivet.split(/\s+/, 2);
    this.$(selector).each(function() {
      // `this` is pointing to DOM el here
      binding.buildBinding('Binding', this, rivet[0], rivet[1]);
    });
  });
  // finally resort bindings (copy-pasted from Rivets.View.prototype.build function)
  binding.bindings.sort(function(a, b) {
    var _ref2, _ref3;
    return (((_ref2 = b.binder) != null ? _ref2.priority : void 0) || 0) -
           (((_ref3 = a.binder) != null ? _ref3.priority : void 0) || 0);
  });
}

And now I have two questions:

  1. I see that I use some private code that may be changed later but I can't find better way to do this. And question is: does my code use buildBinding in right way?
  2. Is it looks reasonable to move bindings.sort and other post-binding stuff to separate function with name like updateBindings. Then users will be able to call it after such custom binding?

Thanks!

hogart commented 9 years ago

Why so complex, why not just:

// in common ancestor
// override if needed
bindings: function () {
    var bindings = {};
    if (this.model) {
        bindings.model = model;
    }
    if (this.collection) {
        bindings.collection = this.collection;
    }

    return bindings;
}

// somewhere in onRender
Rivets.bind(this.el, _.result(this, 'bindings'));
cybernetlab commented 9 years ago

@hogart because I want to keep data bindings in code (not in templates)