gmac / backbone.epoxy

Declarative data binding and computed models for Backbone
http://epoxyjs.org
MIT License
615 stars 89 forks source link

Binding to attributes that haven't been added to the model (yet) #86

Closed kellylawson closed 9 years ago

kellylawson commented 10 years ago

We're evaluating Epoxy for a fairly large scale application that has a significant data driven aspect. In our design, are basically not explicitly creating model attributes on the client in most cases, they either come from the server or they are added on the client after the initial model creation.

This design makes it difficult to use Epoxy as the binding context is driven by the attributes defined on the model. We end up running into the following exception in bindElementToView:

        try {
            var parserFunct = bindingCache[declarations] || (bindingCache[declarations] = new Function('$f','$c','with($f){with($c){return{'+ declarations +'}}}'));
            var bindings = parserFunct(filters, context);
        } catch (error) {
            throw('Error parsing bindings: "'+declarations +'"\n>> '+error);
        }

I'm looking for a solution to this problem rather than just choosing a different framework because the syntax provided by Epoxy is really elegant. So far, this is what I've thought of for options:

  1. Add some code to an Epoxy extension in our app that will evaluate the binding declarations before any call to applyBindings, then add any references fields to the 'defaults' hash on the model. This is a hack workaround.
  2. Modify the Epoxy helper function 'addSourceToViewContext' to create an accessor function for anything referenced in the binding declarations - even if it's not in a model yet. This is similar to #1, but instead of adding defaults to the model, it would use the binding declarations (whether declarative or in the 'bindings' hash) as the 'source of truth' for what we want to bind to.
  3. Replace the 'throw' in the code snippet above and bury the exception, then log an error and let the client manage when they feel they need to call applyBindings again. This basically lets the client partially bind a view as applyBindings will only create a binding for the fields that are available in the context and ignore everything else. This isn't great as it requires the client to call applyBindings more than once, which could have a performance impact.

Those are the potential workarounds/solutions that I can think of with my current understanding of the Epoxy code. Can you help me understand if there is a better solution? Ideally if I implement something, I'd like to submit a pull request and get it back into main.

Thanks, and great work on Epoxy!

omichowdhury commented 10 years ago

Just a note that this is also an issue in our app. We resort to setting default values on model attributes which have not been set yet, and then calling applyBindings.

An easier to implement option would be to create the attribute on the model if one is not found. This obviously brings its own issues but in metadata driven applications this would be the simplest way of solving it (assuming the bindings are being created from metadata).

gmac commented 9 years ago

This is a problem that Epoxy is not interested in solving. If you don't know what field names you're going to be binding, that would imply both your model and view layers are going to be moving targets – which quite frankly – makes your situation a bad case for workflow automation IMHO.

If you're trying to bind your model to a view before the model has loaded, no problem: just define default attributes on the model. If you don't know what fields your model is going to have when it loads, then what are you storing in your database?!

Epoxy is really good at binding known fields to known DOM nodes, and wants to do that job well. Epoxy does not want to attempt automation of binding unknown fields to unknown nodes, because quite frankly – you'll probably be pretty displeased with the reliability of those results.