0

jsTree (1.0-rc3) を Knockout.js (2.2.1) で動作させようとしています。

jsFiddle の例を参照してください: http://jsfiddle.net/adeconsulting/qfr6A/

注: この問題を引き起こしている可能性のあるライブラリ間の競合が発生した場合に備えて、Visual Studio プロジェクトにできるだけ一致するように、Fiddle にいくつかの JS リソースを含めました。

Fiddle を実行し、jsTree をナビゲートします。これは、物理的な場所と種類によるサーバーのリストです。ajax の呼び出しと応答を確認できるように、Firebug のコンソールを開くと役立ちます。リーフ ノードをクリックすると、ajax 呼び出しが行われ、サーバーの詳細が取得され、値が Knockout バインディングを使用するフォームが表示されます。非リーフ ノードが選択されているときにフォームを非表示にします。

葉ノードを初めてクリックしたときに機能します。その後、Knockout はリーフ ノード クリックのフォームを更新しません。ただし、[編集] ボタンをクリックすると、突然、最新のサーバーの詳細が表示されます。

jsTree バインディングと Knockout バインディングの間に競合があると考えていますが、どこからトラブルシューティングを開始すればよいかわかりません。

stackoverflow には明らかに少なくとも 1 つのコード ブロックが必要なため、Fiddle の JavaScript 部分を次に示します。

// Global vars:
var prevJsTreeNodeId = null;
var serverModelBindingsApplied = false;
var serverLoadInProgress = false; 

/*
 * The knockout.js view model
 */
var ServerViewModel = function () {
    // Data
    var self = this;
    self.IsReadOnly = ko.observable(true);       // the form's input mode
    self.btnEditSave = ko.observable("Edit");    // the Edit/Save button text
    self.Server = ko.observable({});             // the Server object

    // Operations
    self.setEditable = function () {
        self.IsReadOnly(false);
        self.btnEditSave("Save");
    };

    self.setReadOnly = function () {
        self.IsReadOnly(true);
        self.btnEditSave("Edit");
    };

    self.doEditSave = function () {
        var flag = self.IsReadOnly();
        if (flag) {
            // switch to Edit mode
            self.setEditable();
        }
        else {
            // switch back to readOnly
            self.setReadOnly();
        }
    };

    // use ajax to update the knockout.js view model's Server object for the specified server name
    self.load = function (serverName) {
        if (!serverLoadInProgress) {
            serverLoadInProgress = true;
            // use ajax to retrieve the server's details
            var data = {
              json: JSON.stringify({
                   ServerName: serverName,
                   PrimaryIP: "1.2.3.4",
                   BrandDesc: "Dell",
                   OSDesc: "Windows 2003 Server",
                   Location: "xyz"
              }),
              delay: 1
            };
            $.ajax({
                url:"/echo/json/",
                data:data,
                type:"POST",
                success:function(response)
                {
                   console.log(response);
                   window.ServerViewModelInstance.Server = ko.mapping.fromJS(response);
                   // apply bindings the first time we retrieve a Server object
                   if (!serverModelBindingsApplied) {
                      ko.applyBindings(window.ServerViewModelInstance,
                                       document.getElementById('servercontent'));
                      serverModelBindingsApplied = true;
                   }  
                   else {
                     // hmmm... updating the view model's .Server property doesn't trigger the 
                     //  form to be updated, yet if we click the Edit button, the new values
                     //  suddenly appear, so try emulating that here...
                     self.setReadOnly();
                   }
                }
            });

           serverLoadInProgress = false;
        }
    };
};    // ServerViewModel

/*
 * document load 
 */
$(function () {
    // configure the jsTree
    $("#divtree")
      .jstree({
          "themes": { "theme": "default", "dots": true, "icons": true },
          "plugins": ["themes", "html_data", "ui", "types"],
          "types": {
              "type_attr": "tag",   // the attribute which contains the type name
              "max_depth": -2,      // disable depth check
              "max_children": -2,   // disable max children check
              "valid_children": ["root"],
              "types": {
                  "root": {
                      "valid_children": ["level1"]
                  },
                  "level1": {
                      "valid_children": ["level2"],
                      "start_drag": false,
                      "move_node": false,
                      "delete_node": false,
                      "remove": false
                  },
                  "level2": {
                      "valid_children": ["leaf"],
                      // use the theme icon for the level2 nodes
                      "start_drag": false,
                      "move_node": false,
                      "delete_node": false,
                      "remove": false
                  },
                  "leaf": {
                      "valid_children": "none"
                  }
              }
          }
      });

    // register to receive notifications from #divtree when a jsTree node is selected
    $("#divtree").bind("select_node.jstree", function (event, data) {
          // data.rslt.obj is the jquery extended node that was clicked
          var key = data.rslt.obj.attr("key");
          var id = data.rslt.obj.attr("id");
          if (id == prevJsTreeNodeId) {
              // user clicked the same node, nothing to do
              return;
          }
          prevJsTreeNodeId = id;

          // when a jsTree node is selected, reset the knockout.js view model to read only
          window.ServerViewModelInstance.setReadOnly();

          var idx = key.indexOf("Server");
          if (idx === 0) {  // "Server|servername"
              // show the "servercontent" div
              $("#servercontent").show();
              // display the server details
              var serverName = key.substr(idx + 7, key.length);
              window.ServerViewModelInstance.load(serverName);
          }
          else {
              // hide the "servercontent" div
              $("#servercontent").hide();
          }
      });


    // hide the "servercontent" div
    $("#servercontent").hide();

    // instantiate the knockout.js view model
    window.ServerViewModelInstance = new ServerViewModel();
});  // document ready

// initialization timer routine to select the main jsTree node
setTimeout(function () {
    // open the root node
    $.jstree._reference("#divtree").open_node("#root");
}, 500);
4

1 に答える 1

2

下の書式設定が不適切で申し訳ありません - このエディタは私の友人ではありません... :-/
あなたの理解が正しければ、クリックしたツリー ノードの詳細パネルが正しいデータで更新されません。

次のことを試してください:
変更:
window.ServerViewModelInstance.Server = ko.mapping.fromJS(response);
を:
window.ServerViewModelInstance.Server(response);

(たとえば、一度だけバインドする最初の ko.observable を上書きせず、代わりにその値を更新します)

そして、オブザーバブルにバインドするビューで..たとえば、代わりに: に
... "value: Server.ServerName, ...
変更します:
... "value: Server().ServerName, ...
(たとえば、プロパティにアクセスする前に関数を実行します)
ツリー内の新しいサーバー名ノードをクリックすると機能し、フォームを更新します (試してみましたfirefox)
変更されたコードを含む例のコピーは、http: //jsfiddle.net/RZ92g/2/にあります。

于 2013-01-29T22:13:20.443 に答える