【问题标题】:JQuery UI Tabs Issue with Knockout binding of observableArray带有 observableArray 的 Knockout 绑定的 JQuery UI 选项卡问题
【发布时间】:2013-08-19 16:00:40
【问题描述】:

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

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

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

一些背景:

  • 数据来自 JSON 数组。它们是循环引用。
  • 我只使用数组的第一个条目。新来的不止一个,但我必须使用 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());

【问题讨论】:

  • 您能解释一下在给定的小提琴中什么不起作用吗?或者你能发布一个重现问题的帖子吗?

标签: jquery user-interface knockout.js tabs


【解决方案1】:

感谢您提出有趣的问题。正确答案隐藏在您使用 foreach 和 with 绑定的实验中,这两者都会导致子节点完全重新呈现。

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

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

显而易见的解决方案是截取内容呈现的时刻并以某种方式重新初始化选项卡。 foreach 绑定有一个内置选项 afterRender 允许挂钩这一刻。我猜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/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-01
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多