【问题标题】:Knockout data-bound bootstrap carousel issue淘汰赛数据绑定引导轮播问题
【发布时间】:2015-03-24 07:20:57
【问题描述】:

我在更新/重新渲染绑定到 Knockout 可观察数组 (self.Notes) 的引导轮播控件数据时遇到了困难。我已经大大简化了提供的代码,因为它太不明智了。

页面加载时一切正常,但是当调用 self.RemoveNoteFromReviewSetup 并修改数组时,轮播完全消失了。当我检查 dom 时,所有标记都在那里,并且标记反映了淘汰赛应对 dom 所做的更改。然而,这是奇怪的部分,当只有 self.Notes 的第一个(索引 0)元素被更新时,轮播会根据更新后的数组 self.Notes 再次呈现。当数组中的任何后续项发生更改时,轮播就会消失。

我遗漏了很多代码,所以如果您需要查看其他内容,请告诉我。

这让我发疯了,我正在考虑只触发一个页面重新加载命令,以便从一开始就呈现所有内容。但是,这当然会破坏整个 Knockout 方法。

非常感谢任何指针。

HTML:

<!-- ko foreach: Reviews -->
<div class="flashcards-controls">
<button id="btnSlideRight" class="btn btn-custom pull-right flatleft flatright" data-bind="click: NextNote"><i class="fa fa-angle-double-right"></i></button><button id="btnSlideLeft" class="flatleft flatright btn btn-custom pull-left" data-bind="click: PrevNote"><i class="fa fa-angle-double-left"></i></button>
<div class="container text-center">
    <span class="badge badge-notecounter"><span data-bind="html: NoteCounter"></span> / <span data-bind="html: Notes().length"></span></span>
</div>
</div>
<div class="container flashcards" id="flashcards-container">

<!-- Carousel
    ================================================== -->
<div id="fashcardsCarousel" class="carousel slide" data-wrap="false" data-interval="false">
    <!-- Indicators -->
    @*    <ol class="carousel-indicators" data-bind="visible: Notes().length > 1, foreach: Notes">
            <li data-target="#fashcardsCarousel" data-bind="attr: { 'data-slide-to': $index }, css: { 'active': $index() == $parent.CurrentNoteIndex() }, click: $parent.NextNote"></li>
        </ol>*@
    <!-- Slides -->
    <div class="carousel-inner" data-bind="foreach: { data: Notes, afterRender: $parent.postCarouselRenderEvent }">
        <div class="item" data-bind="css: { 'active': $index() == $parent.CurrentNoteIndex() }">
            <div class="row">
                <div class="col-xs-12">
                    <div class="panel panel-default">
                        <div class="panel-heading clearfix">
                            <div class="btn-group pull-right">
                                <button data-bind="click: ToggleTagEditor, attr: { id: 'btnTagEditor' + GlobalClientId() }" class="btn btn-sm btn-custom">
                                    <i class="fa fa-tags fa-fw"></i>
                                </button>
                                <button class="btn btn-sm btn-custom">
                                    <i class="fa fa-book fa-fw"></i>
                                </button>
                                <button data-bind="click: ShowInfo, attr: { id: 'btnInfo' + GlobalClientId() }" class="btn btn-sm btn-custom">
                                    <i class="fa fa-info fa-fw"></i>
                                </button>
                            </div>
                            <h5><strong data-bind="    text: Title"></strong></h5>
                        </div>
                        <div class="panel-body" data-bind="html: Content, visible: Content">
                        </div>
                        <div class="panel-body" data-bind="style: { display: IsLoading() == false ? 'none' : '' }">
                            <div class="text-center text-muted">
                                <i class="fa fa-refresh fa-spin"></i><br />
                                Loading note content
                            </div>
                        </div>
                    </div>
                </div>
            </div>

        </div>
    </div>
    <!-- Controls -->
    <!-- ko if: Notes().length > 1 -->
    @*<a class="left carousel-control"We added support for all common image types. In other words, pictures will now show up when you review your @evernote notes :-) href="#fashcardsCarousel" data-slide="prev" data-bind="click: PrevNote"><span class="glyphicon glyphicon-chevron-left"></span></a>
        <a class="right carousel-control" href="#fashcardsCarousel" data-slide="next" data-bind="click: NextNote"><span class="glyphicon glyphicon-chevron-right"></span></a>*@
    <!-- /ko -->
</div>
<!-- /.carousel -->

</div>
<div id="popoverStagingArea" data-bind="foreach: { data: Notes, afterRender: $parent.postTagPopoversRenderEvent }" style="display: none;">
<div data-bind="attr: { id: 'tagEditor' + GlobalClientId() }">
    <select multiple></select>
    <p class="text-muted text-center" data-bind="visible: TagsUpdating" style="margin: 0;"><i class="fa fa-refresh fa-spin"></i></p>
    <div data-bind="attr: { id: 'tagRemovalConfirmation' + GlobalClientId() }" style="display: none">
        <button class="btn btn-sm btn-custom btn-block" data-bind="click: RemoveTagPendingRemoval">Only remove tag from note</button>
        <button class="btn btn-sm btn-custom-warning btn-block" data-bind="click: RemoveTagAndDeleteNoteFromReviewSetup">Also remove note from filter</button>
        <button class="btn btn-sm btn-default btn-block" data-bind="click: CancelTagRemoval">Cancel</button>
        <p class="text-center" style="margin-top: 3px;">(<a data-bind="click: TagRemovalExplainer().slideDown('fast')" href="#">what is this?</a>)</p>
        <div data-bind="attr: { id: 'tagRemovalExplainer' + GlobalClientId() }" style="display: none;">
            <p>
                When you setup filter <strong data-bind="text: $parent.SetupName"></strong> you selected tag <span class="label label-success" data-bind="text: TagPendingRemoval().Name"></span> as part of the search criteria. We thought you might want to have the option to either just remove the tag from the note and save it to Evernote, or also delete this note from any subsequent reviews that are part of <strong data-bind="text: $parent.SetupName"></strong>.
            </p>
            <p class="text-center">
                (<a data-bind="click: TagRemovalExplainer().slideUp('fast')" href="#">hide</a>)
            </p>
        </div>
    </div>
</div>
</div>
<!-- /ko -->

JS:

        function Review(reviewItem) {
        //code removed//
            self.RemoveNoteFromReviewSetup = function (note) {                   
                var apiRemoveNoteString = "/api/review/" + self.Guid + "/note/" + note.Guid;
                $.ajaxq("notes", {
                    type: "DELETE",
                    url: apiRemoveNoteString,
                    headers: { "Authorization": "Token " + $.cookie("rat") },
                    success: function (replacementNote) {
                        var originalNoteIdx = self.Notes.indexOf(note);
                        self.Notes.replace(self.Notes()[originalNoteIdx], new Note(replacementNote, self));
                        self.Notes()[originalNoteIdx].GetContent();
                        console.log(self.Notes()[originalNoteIdx]);
                        self.Notes()[originalNoteIdx].InitTagEditor();
                    },
                    error: function (jqXHR, textStatus, errorThrown) {
                        alert("We could not remove a note for you at this time. Please try again later.");
                    },
                    complete: function () {

                    },
                    dataType: "json"
                });
            }
        }

【问题讨论】:

  • 请提供一个简单的 jsfiddle 来演示问题
  • 我很同情,但恐怕您的问题中的代码太多,而且代码太少,我们无法(方便地)帮助您。太多了,因为其中肯定有许多与问题无关的东西。它太少了,因为它不足以重现问题(尝试使用编辑器工具栏制作 Stack Snippet,reproduce 你的问题)。
  • 也许这篇文章对你有用:stackoverflow.com/questions/19029224/…
  • 感谢大家的关注和精神支持。我解决了这个问题。请在下面查看我的答案

标签: jquery twitter-bootstrap knockout.js twitter-bootstrap-3


【解决方案1】:

好的,我想通了。这与淘汰赛无关。在仔细查看重新渲染的轮播标记后,我注意到没有一张幻灯片具有“活动”类,Bootstrap 使用该类来确定当前幻灯片。像这样手动/以编程方式添加此类后:

var slide = $("#yourselector")[slideIndex];
$(slide).addClass("active");

整个轮播再次可见,所有行为都完好无损:-)。

这是我生命中的另外 1.5 天,我不会回来,但我会安慰自己,告诉自己我已经获得了关于 Knockout 和 Bootstrap 的内部库工作的宝贵知识......

【讨论】:

    猜你喜欢
    • 2013-10-08
    • 1970-01-01
    • 2014-09-18
    • 2014-04-09
    • 1970-01-01
    • 2014-03-31
    • 2013-03-06
    • 2016-11-06
    相关资源
    最近更新 更多