Question

What I am after is a piece of code that could provide me a clean and simple one-way solution to bind the changes from DOM to the object that is used to render it.

Example: And object

{name: 'Joe'}

is used to render the Mustache template

<div><input val="{{name}}" /></div>

How can I match the change event in the inputfield to the correct property?

What about iterations?

{{#users}}
<div><input val="{{name}}" /></div>
{{/users}}

Is there a such thing?

Edit: And yes, I am aware of Backbone, Angular, Ember, younameit. However, what I need is a specific case to Mustache/Handlebars.

Was it helpful?

Solution 5

Well, managed to find a way to do simple data binding via shadow dom solution. It's not the perfect solution but it will do for now.

OTHER TIPS

Ractive is exactly this. Mustache with data binding. https://ractive.js.org

What you are asking for called Angular.js

There is little bit different approach in other similar frameworks like knockout.js, batman.js etc.

Check sample todo application to see how different framework do it.

UPDATE:

On the other hand, if all your "bindings" are going to be simple and you do not care much about syntax there are two approaches that you can use with just jquery in order to minimize ammount of code working with input fields:

  1. one input field per model field and just one model

var model = {
  a: 1,
  b: 2,
  c: 3
}
$('#myForm').on('blur', 'input', function(e) {
  var $this = $(this),
    field = $this.data('model')
  model[field] = $this.val()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id='myForm'>
  <input type='text' data-model='a' />
  <input type='text' data-model='b' />
  <input type='text' data-model='c' />
</form>

  1. kinda extension of first one you can grouping elements together if you have multiple models and multiple fields per model. Good example is table editor, when each row bound to element in array and has several fields bound to cells in a row

js

var models = { modelA : {...}, modelB: {...}}

$('#myForm').on('blur', 'input', function(e) {
   var $this = $(this), field = $this.data('field')
   , model = $this.data('model') 
   // last line can be smth like $this.closest('div.group').data('model')

   models[model][field] = $this.val()   
})

So to sum up your example:

 {{#users}}
   <div><input data-model='users' data-index='{{ $index }}' val="{{name}}" /></div>
 {{/users}} 

 $('#myForm').on('blur', 'input', function(e) {
    var $this = $(this), index = $this.data('index')
    , model = $this.data('model') 
    window.data[model][index][field] = $this.val()   
 })

Check jtmpl, it should exactly fit your need—render a Mustache template and keep DOM synchronized with model at all times.

Collections and node attributes are supported and your example syntax should work as is (just correct "val" -> "value").

I suggest you look at vue.js - it's now a widely adopted framework and is much lighter than Angular (600kb vs 60kb minified and 20kb if gzipped) and uses mustache-similar syntax.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top