JSFiddle - React, Tailwind, and code Playground
HTML
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0-rc.3/handlebars.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.4.4/underscore-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.0.0/backbone-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.marionette/1.0.1-bundled/backbone.marionette.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/backbone.validation/0.7.1/backbone-validation-min.js"></script>
<script type="text/x-template" id="person-form-template">
<div class="form-horizontal">
<div class="control-group">
<label class="control-label" for="name">Name</label>
<div class="controls"><input class="input" type="text" name="name" id="name" value="{{name}}" /></div>
</div>
<div class="control-group">
<label class="control-label" for="age">Age</label>
<div class="controls"><input class="input" type="number" name="age" id="age" value="{{age}}" /></div>
</div>
<div class="controls">
<button class="btn btn-primary" id="send-btn">Send</button>
<button class="btn" id="cancel-btn">Cancel</button>
</div>
</div>
</script>
<div class="container">
<div id="person-form">
<!-- the actual content comes here! -->
</div>
</div>
CSS
#person-form {
margin-top: 20px;
}
.help-inline.next-line {
margin-top: 5px;
margin-left: 180px;
display: block;
padding: 0;
}
CoffeeScript
# PART 1: tweak backbone validation a little bit
# ===============================================
do ->
# first, allow errorous inputs to update our model
Backbone.Validation.configure
forceUpdate: true
# then disable default callbacks for backbone validation events
_.extend Backbone.Validation.callbacks,
valid: (view, attr, selector) ->
# these are not used
invalid: (view, attr, error, selector) ->
# these are not used
# we are using our custom model events "valid:<attr>" and "invalid:<attr>" to indicate
# when model field is validated
attrValid = (view, attr, selector) ->
# 'view' is not used, views use our implementation ;)
@trigger "valid:#{attr}", attr, selector
attrInvalid = (view, attr, errorMsg, selector) ->
# 'view' is not used, views use our implementation ;)
@trigger "invalid:#{attr}", attr, errorMsg, selector
origValidate = Backbone.Validation.mixin.validate
Backbone.Validation.mixin.validate = (attrs, setOptions) ->
options = setOptions || {}
# "this" refers now to model so we apply it to our validation
# functions, thus can trigger validation events for right model
options.valid = => attrValid.apply(@, arguments)
options.invalid = => attrInvalid.apply(@, arguments)
origValidate.call(@, attrs, options)
# add customized validation to our models, when validations occur, they raise
# model events valid:<attr> and invalid:<attr> to our models. Views may be interested
# in those validation callbacks for showing error messages.
_.extend(Backbone.Model.prototype, Backbone.Validation.mixin)
# PART 2: bind our backbone view to validation events and also for
# input changes so that model changes automatically when input changes
# =======================================================================
do ->
# This defines which element's attribute will be used...