3. Bottom Line Upfront
• What is Knockout
o MVVM framework for Javascript
• Observable View Models
• Declarative and Templated Views
• Enables simpler, reusable, frontend and cleaner communication with
backend
• Geek or Presenter (definitely Geek)
o Slow me down
o Ask questions
o Give me feedback so I can get better
• Goal
o Scratch the surface of knockout
4. Model serialized Model serialized
as HTML as Form / Query
string Dictionary
Must know how
model was
serialized
5. • But we’ve always done it that way – why not…
• Complex communication interface (send one thing and receive
another)
• Model Binding against a dictionary seems simple but quickly gets
Model serialized Model serialized
complex (object graphs, as HTML
arrays)
as Form / Query
• View is now server side (Razor, C#) AND client side (javascript, css)
string Dictionary
creating coupling between these layers
• View ultimately ‘lives’ in the DOM not in CLR / Razor
• Client side code is coupled to the view and not the model
• Difficult to reuse code in mobile, etc.
Must know how
model was
serialized
6. Interface is now
consistently JSON
Javascript is now
responsible for
presenting JSON
and
communicating
JSON back to
server
7. • Much cleaner communication interface
• Can write multiple presentation layers (ie. mobile) on top of the same
communication interface
• Model binding is radically easier (Json Model Binder)
Interface is now
consistently JSON
Javascript is now
responsible for
presenting JSON
and
communicating
JSON back to
server
10. Demo
• Prototype
• Baby steps
o Observable
o View model
o Model
o Array
• Ugh, where’s the View (look at prototype)
o View
o View Array (clean up entry should be ViewModel)
o Its all connected
o Templates (edit / view, table / list) (before / after / cleanup)
o Computed (simple, prototype)
o More bindings (css, if and value, value options, click, event, more click)
• Actions
o Root ViewModel (with / root)
o Strategy for dealing with server (get)
• Binding Handlers
o Editable
o If view code is bleeding into your view model – its time for a binding handler
• Ie – animations,
• ASP.NET
o JSON
o WEB API
o Bundles
11. Gotchas
• Dates –
o http://feedproxy.google.com/~r/ScottHanselman/~3/MTbztRtN2l8/OnTheNight
mareThatIsJSONDatesPlusJSONNETAndASPNETWebAPI.aspx Mapping
• Don’t self close tags – unless there will never be anything
inside that tag – its tempting…
• Careful that you don’t ‘un-observe’ an item by not
setting properly
• Be mindful of whether it is observable or not
• Template is a string….
• Misleading errors
12. Resources
• Will post slides / code
• http://jsfiddle.net/
o Decompose a problem using this sandbox
• http://knockoutjs.com/
o Interactive tutorials – experience them
• http://www.knockmeout.net/
o Tons of experience captured in this blog
• http://channel9.msdn.com/Events/MIX/MIX11/FRM0
8
o Great video from early days of Knockout
• http://channel9.msdn.com/Events/TechDays/TechD
ays-2012-Belgium/199
o Recent video of Knockout + Web Api + Upshot = Amazing!
Editor's Notes
We all bleed red…Load habitometerLoad fiddlesClose google talk, email, etc.Increase font sizeSwagConfirm timelineCurious about MyWebGrocer
Now transferring data – not presentation…. Which means… we can put another presentation (mobile, etc.) no top
Now transferring data – not presentation…. Which means… we can put another presentation (mobile, etc.) no top
How about validationHow about back buttonHow about complex view modelsHow about to / from serverInlineAJAXWep API
Observables Introduce ko.observable()Subscribe and alert, timeout, alert starting valueCan have an initial value to ko.observable()Subscribe can see before and afterIntroduce ko.observableArrayhow to properly initialize and ‘clear’ them (null, [])Note that for push we call on observable array – while length we call on the actual array
TemplatingBe careful … template name is a stringReusableEasily switch between templatesDisplay more than one template
ko.bindingHandlers['editable'] = { init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext){ var node = $(element); var span = $('<span></span>'); node.append(span); //ko.bindingHandlers.text.init(span[0], valueAccessor, allBindingsAccessor, viewModel, bindingContext); var text = $('<input type="text" />'); text.hide(); node.append(text); ko.bindingHandlers.value.init(text[0], valueAccessor, allBindingsAccessor, viewModel, bindingContext); text.blur(function(){ text.hide(); span.show(); }); node.click(function(){ if (span.is(':visible')){ span.hide(); text.show(); text.focus(); } }); }, update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext){ var node = $(element); var span = node.find('span'); var text = node.find('input'); ko.bindingHandlers.text.update(span[0],valueAccessor, allBindingsAccessor, viewModel, bindingContext); ko.bindingHandlers.value.update(text[0],valueAccessor, allBindingsAccessor, viewModel, bindingContext); }};