简体   繁体   中英

KnockoutJS accordion like behaviour with custom binding

I'm trying to build some accordion like functionality with KnockoutJS and custom bindings

So far I've got it half way there:

<div data-bind="foreach: items">
    <div class="item"> <span data-bind="text: name() ? name() : 'New Thing'"></span>

        <br /> <a href="#" data-bind="click: $parent.toggleVisibility">Show / Hide</a>

        <div class="fullDetails" data-bind="accordion: visible">
            <label>Name:</label>
            <input type="text" data-bind="value: name" />
        </div>
    </div>
</div>
<a href="#" data-bind="click: addItem">Add new item</a>

and my Javascript

var ViewModel = function () {
    var self = this;

    self.items = ko.observableArray([new ItemModel()]);

    self.addItem = function (item) {

        ko.utils.arrayForEach(self.items(), function (i) {
            i.visible(false);
        });
        self.items.push(new ItemModel())

    };

    self.toggleVisibility = function (item) {

        ko.utils.arrayForEach(self.items(), function (i) {
            i.visible(false);
        });

        item.visible(!item.visible())
    };
};

var ItemModel = function () {
    this.visible = ko.observable(true);
    this.name = ko.observable();
}

ko.bindingHandlers.accordion = {
    init: function (element, valueAccessor) {
        var value = valueAccessor();
        $(element).toggle(ko.utils.unwrapObservable(value));
    },

    update: function (element, valueAccessor) {
        var value = valueAccessor();

        ko.utils.unwrapObservable(value) ? $(element).slideDown() : $(element).slideUp();
    }
};

ko.applyBindings(new ViewModel());

Also on JSFiddle: http://jsfiddle.net/alexjamesbrown/PPAsK/

Some issues I am having:

Show/Hide link
This seems to scroll up and then immediately scroll down again.

Adding a new item
I was trying to get the item currently visible to slideUp , then the new item to slideDown but this isn't working - whatever item is visible slidesUp, but the new item just appears

  • Issue 1:

you are always showing on show/hide link click because the item previously gets reset to visible(false). Fix:

    ko.utils.arrayForEach(self.items(), function (i) {

        //don't bother with the item, we take care of it later
        if (item !== i) {
            i.visible(false);
        }

    });
  • Issue 2:

you need to start with the added item hidden, then apply self.toggleVisibility(newItem) This will take care of hiding the others and animating the new one

self.addItem = function (item) {
        var newItem = new ItemModel();

        //make sure it starts hidden
        newItem.visible(false);
        self.items.push(newItem);

        //highlight it the usual way
        self.toggleVisibility(newItem);
    };

fixed version here: http://jsfiddle.net/tudorilisoi/3LzbT/8/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM