Skip to content

Instantly share code, notes, and snippets.

@carpeliam
Created March 13, 2012 23:38
Show Gist options
  • Save carpeliam/3eb37fbb4a4b720f0537 to your computer and use it in GitHub Desktop.
Save carpeliam/3eb37fbb4a4b720f0537 to your computer and use it in GitHub Desktop.
super-sexy model binding for a collection
ProjectPages.Views.Projects ||= {}
class ProjectPages.Views.Projects.KeyMilestoneView extends Backbone.View
templates:
show: JST["backbone/templates/projects/key_milestones/show"]
edit: JST["backbone/templates/projects/key_milestones/edit"]
form: JST['backbone/templates/projects/key_milestones/_form']
modalHeader: JST["backbone/templates/shared/modal/header"]
modalFooter: JST["backbone/templates/shared/modal/footer"]
events:
'click .edit': 'edit'
'click .add-link': 'addMilestone'
'submit': 'save'
'hidden .modal': 'removeEdit'
edit: (e) ->
dialog = $(@make('form', id: 'editSidebarDialog', class: 'modal fade')).
append(@templates.modalHeader(title: 'Edit Key Milestones')).
append(@templates.edit()).
append(@templates.modalFooter())
body = dialog.find('tbody')
## AWESOME PART #2 (look down at #1 first): appends bound markup to the page
@collection.each (km, i) => body.append @bindModelToTemplate(@templates.form, km, i)
dialog.find('.add-link:not(:last)').hide()
dialog.appendTo(@$el).modal()
e.preventDefault()
removeEdit: (e) ->
@$('#editSidebarDialog').remove()
e.preventDefault()
## AWESOME PART #1: takes a template function, model, and index. applies the model to the template,
## looks through the resulting markup and binds the model and the fragment together.
## returns fragment back to caller, ready to be appended to the page.
bindModelToTemplate: (template, model, index=new Date().getTime()) ->
expr = new RegExp("#{model.collection.relationship}_attributes\\[#{index}\\]\\[([^\\]]+)\\]")
fragment = $(template(km: model, index: index))
fragment.find(':input').each ->
if result = $(@).attr('name').match(expr)
field = result[1] # result[0] == the whole match, which is the name attr itself
model.bind "change:#{field}", => $(@).val(model.get(field))
$(@).bind 'change', ->
attrs = {}; attrs[field] = $(@).val()
model.set(attrs)
return fragment
addMilestone: (e) ->
addLink = $(e.target)
body = addLink.closest('tbody')
## AWESOME PART #2.5 does same thing as AWESOME PART #2, but with default timestamp
body.append @bindModelToTemplate(@templates.form, new ProjectPages.Models.ProjectChild)
addLink.remove()
e.preventDefault()
save: (e) ->
# magic happens, a miracle occurs, then...
console.log 'serializeArray()', @$('form').serializeArray()
data = _(@$('form').serializeArray()).reduce (set, h) ->
set[h.name] = h.value
set
, {}
console.log 'reduction', data
# @collection.save()
@$('#editSidebarDialog').modal('hide')
e.preventDefault()
render: ->
$('.box', @$el).html @templates.show(keyMilestones: @collection)
return this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment