2

我从 JQuery UI 选项卡中得到一个奇怪的问题:

当我将带有 Knockout 的数据绑定到某些文本字段时,JQuery UI 选项卡不再起作用。如果我禁用 ko.applyBinding,那么它可以工作。如果我从淘汰赛中删除“with”或“foreach”标签,则标签工作正常。

但是如果我使用“with”标签,并且我想要在这个区域中有一个 JQuery 选项卡,那么这些选项卡将停止工作,而 jsConsole 中没有任何错误。

一些背景:

  • 数据来自 JSON 的数组。它们是循环引用。
  • 我只使用数组的第一个条目。更新的比 One 更多,但我必须使用 observaleArray 来使用数据。
  • 我想在选项卡中显示引用的数据。Example down 没有植入这个,因为标签不起作用。

链接:http: //jsfiddle.net/7rPR3/23/

代码:

<table>
    <tbody data-bind="with: First">
    <!-- <tbody> -->
        <tr>
            <td>PersoNr:</td>
            <td><input data-bind="value: PersoNr" type="text" disabled /></td>
        </tr>
        <tr>
            <td>Name:</td>
            <td><input data-bind="value: Name" type="text"/></td>
        </tr>
        <tr>
            <td>Vorname:</td>
            <td><input data-bind="value: Vorname" type="text"/></td>
        </tr>
        <tr>
            <td>Save:</td>
            <td><button data-bind="click: $root.saveData">Save</button></td>
        </tr>
        <tr>
            <td colspan="2">

                <div id="StammTabs">
                    <ul>
                        <li><a href="#StammAdresseTab">Adresse</a></li>
                        <li><a href="#StammFunktionTab">Funktion</a></li>
                        <li><a href="#StammVertragTab">Vertragsdaten</a></li>
                        <li><a href="#StammTeamTab">Team</a></li>
                        <li><a href="#StammBankSozTab">Bankdaten/Sozialvers</a></li>
                        <li><a href="#StammKrankenversicherungTab">Krankenvers.</a></li>
                        <li><a href="#StammSonstigesTab">Sonstiges</a></li>
                        <li><a href="#StammUnterlagenTab">Unterlagen</a></li>
                    </ul>
                    <div id="StammAdresseTab">

                    </div>
                    <div id="StammFunktionTab">
                        <p>StammFunktionTab</p>
                    </div>
                    <div id="StammVertragTab">
                        <p>StammVertragTab</p>
                    </div>
                    <div id="StammTeamTab">
                        <p>StammTeamTab</p>
                    </div>
                    <div id="StammBankSozTab">
                        <p>StammBankSozTab</p>
                    </div>
                    <div id="StammKrankenversicherungTab">
                        <p>StammKrankenversicherungTab</p>
                    </div>
                    <div id="StammSonstigesTab">
                        <p>StammSonstigesTab</p>
                    </div>
                    <div id="StammUnterlagenTab">
                        <p>StammUnterlagenTab</p>
                    </div>
                </div>




            </td>
        </tr>
    </tbody>

</table> 

JS:

      var tabs = $("#StammTabs").tabs({
          select: function (event, ui) {
              alert("hallo!");
          }
      });



var data = [];




    var stammViewModel = function() {
        var self = this;
        self.stammPersoNr = 'XX0000';
        self.data = ko.observable(data);
        self.dataArray = ko.mapping.fromJS(data);
        self.First = ko.computed(function () {
            return self.dataArray()[0];
        });

        var json = '[{"$id":"1","ID":299,"PersoNr":"TZ1155","Name":"Mustermann","Vorname":"Martin","Geschlecht":"m","Eintritt":null,"Austritt":"2999-01-01T00:00:00","Geburtsdatum":null,"Staatsangehörigkeit":null,"aktuellerStatus":8,"Intranet":false,"Bild":null,"Bemerkung":null,"User":null,"Userdatum":null,"StammAdr":[{"$id":"2","ID":205,"PersoNr":"TZ1155","Datum":"2008-01-15T00:00:00","StraßeNr":"Irgendwo. 2","PLZ":12345,"Ort":"Berlin","Tel":null,"Mobil":null,"EMail":null,"User":null,"Userdatum":null,"Stamm":{"$ref":"1"}}]}]';

        alert(json);

        self.loadData = function () {
            if (self.stammPersoNr !== '') {
                $.ajax({
                type: "POST",
                url: " /echo/json/",
                            data: {
                                json:json
                            },
                cache: false,
                success: function(data){
                    ko.mapping.fromJS(data, self.dataArray);
                   }
        });
            } else {

            }

        };
        self.loadData();

    };     

    ko.applyBindings(new stammViewModel());
4

1 回答 1

3

感谢您提出有趣的问题。正确答案隐藏在您的实验foreachwith绑定中,这两者都会导致子节点的完全重新渲染。

看看你的小提琴是如何一步一步地执行的:

  1. UI 选项卡在 #StammTabs 元素中初始化
  2. 您的模型初始化
  3. tbody内容保存在某处并与 DOM 分离,因为 observableFirst尚未初始化(with绑定的正常行为)。
  4. 模型加载数据。
  5. ObservableFirst被对象填充。
  6. 通过使用给定值tbody复制保存来生成新的。tbody
  7. Newtbody附加到 DOM(事件处理程序不是从 original 复制的tbody)。
  8. 选项卡看起来有样式,但未重新分配事件处理程序(选项卡不起作用)。

显而易见的解决方案是截取内容呈现的时刻并以某种方式重新初始化选项卡。foreachbinding 有一个内置选项afterRender,允许 hook 此刻。我猜想with绑定没有afterRender选项(我尝试过,但看起来该选项无法使用with)。

所以恕我直言,最好的解决方案是使用自定义绑定来初始化 UI 选项卡小部件。First这种方法保证在每次更改值后正确初始化选项卡。例如:

ko.bindingHandlers.uiTabs = {
    init: function(el){
        $(el).tabs({ select: function(){ alert("hello"); } });
    }
};

并明确绑定到#StammTabs:

<div id="StammTabs" data-bind="uiTabs: 1">

在这种情况下,任何值都是允许的,但您可以重写自定义绑定以获得更灵活的行为。

更新小提琴 - http://jsfiddle.net/7rPR3/24/

于 2013-08-19T18:50:15.887 回答