Wednesday 24 October 2012

Knockoutjs - using the same variable with the 'with' binding and nested 'text' binding

I'm working on a demo for a meetup presentation next week, and initially I had something like this:
 <!DOCTYPE html>  
 <html>  
 <head>  
 <script type="text/javascript" src="js/knockout-2.1.0.js"></script>  
 </head>  
      <body>  
      <p>Choose your costume:   
           <select data-bind="options: availableCostumes, optionsCaption: 'Choose one...', value: selectedCostume"></select>  
      </p>  
      <div data-bind="with: selectedCostume">  
           On Halloween this year, I will be a <span data-bind="text: makeScaryCostume"></span>.  
      </div>  
      </body>  
      <script type="text/javascript">  
        function CostumeViewModel() {  
           var self = this;  
           self.selectedCostume = ko.observable(null);  
           self.availableCostumes = ko.observableArray(['Pirate', 'Ghost', 'Banana']);  
             self.makeScaryCostume = ko.computed(function() {  
                    return "very scary " + self.selectedCostume();  
             }, self);  
        };  
      ko.applyBindings(new CostumeViewModel());  
      </script>  
 </html>  
However, whenever I run this, the following error message happens:
 Uncaught Error: Unable to parse bindings.  
 Message: ReferenceError: makeScaryCostume is not defined;  
 Bindings value: text: makeScaryCostume knockout-2.1.0.js:48  
 a.a.extend.parseBindingsString knockout-2.1.0.js:48  
 a.a.extend.getBindings knockout-2.1.0.js:48  
 a.h.disposeWhenNodeIsRemoved  
The problem is that the 'with' binding creates a context for the nested elements, so within that inner div, it doesn't have access to the view model. The solution is to use the built-in $root reference, which refers to the view model. From there you can use the computed method.
      <div data-bind="with: selectedCostume">  
           On Halloween this year, I will be a <span data-bind="text: $root.makeScaryCostume"></span>.  
      </div  

No comments:

Post a Comment