尝试将jquery UI和knockout js联合起来时遇到了一些问题。基本上我想创建一个手风琴,其中的项目是通过foreach(或模板)从淘汰赛中添加的。
基本代码如下:
<div id="accordion">
<div data-bind="foreach: items">
<h3><a href="#" data-bind="text: text"></a></h3>
<div><a class="linkField" href="#" data-bind="text: link"></a></div>
</div>
</div>
这里没有什么令人印象深刻的...问题在于,如果我做了类似的事情:
$('#accordion').accordion();
将创建手风琴,但内部div将是标题选择器(默认情况下为第一个子节点),因此效果不是所需的效果。
解决这个问题:
$('#accordion').accordion({ header: 'h3' });
似乎工作得更好但实际上创造了2个手风琴,而不是一个有2个部分...很奇怪。
我试图探索淘汰赛模板并使用“afterRender”来重新演奏div,但无济于事......它似乎只重新渲染第一个链接作为手风琴而不是第二个。可能这是由于我的初学者对jquery UI的了解,无论如何。
你知道如何让一切都协同工作吗?
答案 0 :(得分:13)
我会使用自定义绑定来实现此类功能。
就像RP Niemeyer一样,jQuery Accordion绑定到knockoutjs http://jsfiddle.net/rniemeyer/MfegM/
答案 1 :(得分:6)
我曾尝试整合淘汰赛和JQuery UI手风琴以及后来的Bootstrap可折叠手风琴。在这两种情况下它都有效,但我发现我必须实现一些变通方法才能正确显示所有内容,尤其是在通过knockout动态添加元素时。提到的小部件并不总是知道关于淘汰赛的情况,事情可能会搞砸(div高度错误计算等等)。特别是使用JQuery手风琴时,它倾向于在其认为合适时重写html,这可能是一个真正的痛苦。
所以,我决定使用核心JQuery和Knockout制作我自己的手风琴小部件。看看这个工作示例:http://jsfiddle.net/matt_friedman/KXgPN/
当然,使用不同的标记和CSS可以根据您的需要进行定制。
好处是它完全是数据驱动的,除了你决定使用的css之外,它不会对布局做出任何假设。你会注意到标记很简单。这只是一个例子。这意味着要定制。
标记:
<div data-bind="foreach:groups" id="menu">
<div class="header" data-bind="text:name, accordion: openState, click: toggle"> </div>
<div class="items" data-bind="foreach:items">
<div data-bind="text:name"> </div>
</div>
</div>
使用Javascript:
ko.bindingHandlers.accordion = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
$(element).next().hide();
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var slideUpTime = 300;
var slideDownTime = 400;
var openState = ko.utils.unwrapObservable(valueAccessor());
var focussed = openState.focussed;
var shouldOpen = openState.shouldOpen;
/*
* This following says that if this group is the one that has
* been clicked upon (gains focus) find the other groups and
* set them to unfocussed and close them.
*/
if (focussed) {
var clickedGroup = viewModel;
$.each(bindingContext.$root.groups(), function (idx, group) {
if (clickedGroup != group) {
group.openState({focussed: false, shouldOpen: false});
}
});
}
var dropDown = $(element).next();
if (focussed && shouldOpen) {
dropDown.slideDown(slideDownTime);
} else if (focussed && !shouldOpen) {
dropDown.slideUp(slideUpTime);
} else if (!focussed && !shouldOpen) {
dropDown.slideUp(slideUpTime);
}
}
};
function ViewModel() {
var self = this;
self.groups = ko.observableArray([]);
function Group(id, name) {
var self = this;
self.id = id;
self.name = name;
self.openState = ko.observable({focussed: false, shouldOpen: false});
self.items = ko.observableArray([]);
self.toggle = function (group, event) {
var shouldOpen = group.openState().shouldOpen;
self.openState({focussed: true, shouldOpen: !shouldOpen});
}
}
function Item(id, name) {
var self = this;
self.id = id;
self.name = name;
}
var g1 = new Group(1, "Group 1");
var g2 = new Group(2, "Group 2");
var g3 = new Group(3, "Group 3");
g1.items.push(new Item(1, "Item 1"));
g1.items.push(new Item(2, "Item 2"));
g2.items.push(new Item(3, "Item 3"));
g2.items.push(new Item(4, "Item 4"));
g2.items.push(new Item(5, "Item 5"));
g3.items.push(new Item(6, "Item 6"));
self.groups.push(g1);
self.groups.push(g2);
self.groups.push(g3);
}
ko.applyBindings(new ViewModel());
答案 2 :(得分:1)
你有什么理由不能将手风琴小部件应用到内部div吗?例如:
<div id="accordion" data-bind="foreach: items">
<h3><a href="#" data-bind="text: text"></a></h3>
<div><a class="linkField" href="#" data-bind="text: link"></a></div>
</div>
答案 3 :(得分:1)
我尝试了已接受的解决方案并且有效。因为我得到了以下错误,所以只需做一点改变
Uncaught Error: cannot call methods on accordion prior to initialization; attempted to call method 'destroy'
只需添加以下内容即可使用
if(typeof $(element).data("ui-accordion") != "undefined"){
$(element).accordion("destroy").accordion(options);
}
有关详细信息,请参阅Knockout accordion bindings break
答案 4 :(得分:0)
您可以尝试对其进行模板化,类似于:
<div id="accordion" data-bind="myAccordion: { },template: { name: 'task-template', foreach: ¨Tasks, afterAdd: function(elem){$(elem).trigger('valueChanged');} }"></div>
<script type="text/html" id="task-template">
<div data-bind="attr: {'id': 'Task' + TaskId}, click: $root.SelectedTask" class="group">
<h3><b><span data-bind="text: TaskId"></span>: <input name="TaskName" data-bind="value: TaskName"/></b></h3>
<p>
<label for="Description" >Description:</label><textarea name="Description" data-bind="value: Description"></textarea>
</p>
</div>
</script>
“Tasks()”是一个ko.observableArray,其中填充了带有属性的task-s “TaskId”,“TaskName”,“Description”,“SelectedTask”声明为ko.observable();
“myAccordion”是
ko.bindingHandlers.myAccordion = {
init: function (element, valueAccessor) {
var options = valueAccessor();
$(element).accordion(options);
$(element).bind("valueChanged", function () {
ko.bindingHandlers.myAccordion.update(element, valueAccessor);
});
...
}
答案 5 :(得分:0)
我所做的是,因为我的数据是从AJAX加载的,而我正在显示一个&#34;正在加载&#34;旋转器,我把手风琴连接到ajaxStop,如下:
$(document).ajaxStart(function(){$("#cargando").dialog("open");}).ajaxStop(function(){$("#cargando").dialog("close");$("#acordion").accordion({heightStyle: "content"});});
工作得很好。