MuzzyA
MuzzyA

Reputation: 37

Can't get accordion to work properly in cshtml

I'm following this example: http://jsfiddle.net/rniemeyer/mfegm/

JavaScript

// Using jquery-ui-1.11.4.js
// and   jquery-1.10.2.js
// Creates a few tags to loop through
var tag = {
    UserId: "MuzzyA",
    TagText: "This text should be collapsed in an accordion"
};
self.tags.push(new Tag(tag, null));
self.tags.push(new Tag(tag, null));
self.tags.push(new Tag(tag, null));

var Tag = function(tag, comments) {
    this.tag = ko.observable(tag);
    this.comments = ko.observableArray(comments);
}

CSHTML

<div class="panel-body" data-bind="foreach:tags,accordion: {}">
    <h4>
            <a href="#" data-bind="text: tag().UserId"></a>
    </h4>
    <div>
        // Content here
    </div>
</div>

The result I get from that is just a list, no accordion The result I get from that is just a list, no accordion

I'm not sure what I'm doing wrong.

EDIT: Calling .accordion

function init() {
ko.applyBindings(new ViewModel());

ko.bindingHandlers.accordion = {
    init: function (element, valueAccessor) {
        var options = valueAccessor() || {};
        setTimeout(function () {
            $(element).accordion(options);
        }, 0);

        //handle disposal (if KO removes by the template binding)
        ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
            $(element).accordion("destroy");
        });
    },
    update: function (element, valueAccessor) {
        var options = valueAccessor() || {};
        $(element).accordion("destroy").accordion(options);
    }
}
}

Below is how my view model is set up. I can't really change it, because there's an entire system relying on it. This is why it gets binded the way you see

var ViewModel = function () {
var self = this;
self.tags = ko.observableArray();
}

document.addEventListener("DOMContentLoaded", init, false);

function init() {
  ko.applyBindings(new ViewModel());

}

Upvotes: 0

Views: 247

Answers (1)

Roy J
Roy J

Reputation: 43881

applyBindings can only apply bindings that have been defined. Defining them afterward does not retroactively apply them. I moved the additional binding handler to be defined before the bindings are applied, and I removed the setTimeout, which was allowing the destroys to be called before the accordion was set up.

var Tag = function(tag, comments) {
  this.tag = ko.observable(tag);
  this.comments = ko.observableArray(comments);
}

var tag = {
  UserId: "MuzzyA",
  TagText: "This text should be collapsed in an accordion"
};

var ViewModel = function() {
  var self = this;
  self.tags = ko.observableArray();
  self.tags.push(new Tag(tag, null));
  self.tags.push(new Tag(tag, null));
  self.tags.push(new Tag(tag, null));
}

document.addEventListener("DOMContentLoaded", init, false);


function init() {
  ko.bindingHandlers.accordion = {
    init: function(element, valueAccessor) {
      var options = valueAccessor() || {};
      $(element).accordion(options);

      //handle disposal (if KO removes by the template binding)
      ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
        $(element).accordion("destroy");
      });
    },
    update: function(element, valueAccessor) {
      var options = valueAccessor() || {};
      $(element).accordion("destroy").accordion(options);
    }
  }
  ko.applyBindings(new ViewModel());
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.3/jquery-ui.min.js"></script>
<div class="panel-body" data-bind="foreach:tags,accordion: {}">
  <h4>
            <a href="#" data-bind="text: tag().UserId"></a>
    </h4>
  <div>
    // Content here
  </div>
</div>

Upvotes: 1

Related Questions