Вопрос

I'm building a slideshow of images with previous and next buttons. The images are fetched from a json object. The images display fine without any problem using <img data-bind="attr: { src: images } /> but as soon as I apply return { controlsDescendantBindings: true }, the images stop displaying. And the data-bind on the <img data-bind="attr: { src: images } /> doesn't work anymore.

Do you know what's happening?

Many Thanks

HTML:

<!-- carousel -->
<div class="carousel" data-bind="carousel: true">
    <div class="controls">
        <a href="#" class="prev">Prev</a>
        <a href="#" class="next">Next</a>
    </div>
    <div class="viewport">
        <!-- trip() represent the json object, but it's confidential -->
        <ul data-bind="foreach: trip().boat.decks">
            <li><a href="#"><img class="image" data-bind="attr: { src: images }" /></a></li>
        </ul>
    </div>
 </div>
 <!-- carousel -->

Knockout/JS:

// binding for carousel
ko.bindingHandlers.carousel = {
    init: function (element, valueAccessor) {
        var $carousel = $(element),
            $viewport = $carousel.find('.viewport'),
            $controls = $carousel.find('.controls'),
            $prev = $controls.find('.prev'),
            $next = $controls.find('.next'),
            $slideList = $viewport.find('ul'),
            $slide = $slideList.find('li');

        console.log('carousel starting...');
        console.log('what is element: ', element);
        console.log('what is $element: ', $(element));

        // put active on 1st slide
        $slide.first().addClass('active');

        //TODO: prev btn
        $carousel.on('click', '.prev', function (e) {
            e.preventDefault();

            console.log('Prev btn carousel clicked!');

            $viewport.find('.active').removeClass('active').prev().addClass('active');

            // if arrived at 1st slide, start again from last slide
            if ($viewport.find('.active').index() < 0) {
                $slide.first().removeClass('active');
                $slide.last().addClass('active');
            }
        });

        //TODO: next btn
        $carousel.on('click', '.next', function (e) {

            e.preventDefault();

            console.log('Next btn carousel clicked!');

            $viewport.find('.active').removeClass('active').next().addClass('active');

            // if arrived at last slide, start again from 1st slide
            if ($viewport.find('.active').index() < 0) {
                $slide.last().removeClass('active');
                $slide.first().addClass('active');
            }
        });

        return {
            controlsDescendantBindings: true
        };
    }
};
Это было полезно?

Решение

When you return controlsDescendantBindings: true you tell Knockout not to perform bindings on child elements, that's why no child elements are bound. The documentation on creating custom bindings that control descendant bindings states that:

Normally, bindings that use controlsDescendantBindings will also call ko.applyBindingsToDescendants(someBindingContext, element) to apply the descendant bindings against some modified binding context.

However, in your case you never call ko.applyBindingsToDescendants, so Knockout will never bind child elements.

I'm not sure why you are trying to control descendant bindings in the first place, but you need to either remove that or ensure that call you ko.applyBindingsToDescendants if you want Knockout to bind child elements.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top