4

I am making a KnockoutJS application where it should be possible to view products and when clicking them a detailed view of the selected product should be displayed to the user and an overlay should be put over the other products.

I have managed to get almost all of this working using JQuery and Featherlight.js. I am able to populate the detailed view with KnockoutJS observable variables but the problem I am having is that when the detailed view is displayed (using JQuery) the bindings to the KnockoutJS view model is lost. I want to be able to listen to click events using KnockoutJS (and call the function "update()" in the knockout controller shown in the code below) in the detailed view and update the view based on this event but as of right now this is only possible by using JQuery.

I think the problem is that when opening the detailed view using Featherlight.js a new "context" or instance is created that Knockout no longer have any bindings to. Anyone knows how this can be fixed?

Here is a fiddle: https://jsfiddle.net/d1txamd4/8/

Here is my code:

HTML

<div style="margin-top:2em;" class="row" data-bind="foreach: products">
                   <div class="col l4 m6 s12">
        <div class="card">
            <a href="#" data-bind="click: $parent.showProductDialog">
                <div class="card-image">
                  <img data-bind="attr:{src: image}">
                </div>
            </a>
            <div class="card-content">
              <b data-bind="text: title"></b>
            </div>
            <div class="card-action">
              <p style="float:left;"><span data-bind="text: price"></span> kr</p>
              <a style="float:right;" class="btn disabled">Föreslå</a>
            </div>
        </div>
    </div>
    </div>

<!-- This is the HTML for the lightbox -->
<div class="lightbox">
 <div class="lightbox-content">
      <img data-bind="attr:{src: lightboxImage}"></br>
      <b class="dialog-title" data-bind="text: lightboxTitle"></b>
      <p data-bind="text: lightboxDescription"></p>
 </div>
    <div class="modal-footer">
        <a data-bind="click: update" class="btn">Click me</a>
    </div>
</div>

JavaScript

function ProductCardViewModel() {
    var self = this;

    // Array containing all products
    self.products = ko.observableArray();

    self.lightboxImage = ko.observable();
    self.lightboxDescription = ko.observable();
    self.lightboxTitle = ko.observable();

   self.products = [
       {"id":1,"name":"Cool healine","title":"It's cool to have a cool headline","description":"This text is suppost to describe something","price":700,"image":"http://www.swedishevent.se/se/wp-content/uploads/2010/11/takvandring_top.jpg","categories":[1,4]},{"id":2,"name":"Even cooler headline","title":"A nice headline is the key to success ","description":"What to write, what to write, what to write?","price":500,"image":"http://www.karlliesilva.com/Massage-Therapy-white-flower2.jpg","categories":[2]}
   ];

   self.showProductDialog = function(product) {
        self.lightboxImage(product.image);
        self.lightboxDescription(product.description);
        self.lightboxTitle(product.title);
        $.featherlight('.lightbox');

   };

    <!-- I want to be able to call this function from the lightbox -->
    self.update = function() {
        alert("Success!");
    };
}

ko.applyBindings(new ProductCardViewModel());
Fredrik Schöld
  • 1,588
  • 13
  • 20

2 Answers2

3

There are two issues here.

Issue one

The featherlight plugin appears to create new dom elements and then insert them into the dom. This means that knockout won't have anything bound to these injected elements.

Issue two

The submit binding only works within form elements, please see the knockout documentation

The solution

The solution is two use ko.applyBindings to bind your view model to the injected dom elements and change the submit binding to a click binding.

I have updated your fiddle with a working solution.

Anish Patel
  • 4,332
  • 1
  • 30
  • 45
0

Check out the option persist introduced in version 1.3.0.

Instead of cloning your content, featherlight can instead "steal" it and persist it. This might be more appropriate to the way you bind your code.

Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166