3

ForestModel を使用して JsonRest ストアと dijit.Tree を作成する際に問題が発生しています。Web 上の多くのヒントに従って、JsonRestStore と json データ形式の組み合わせをいくつか試しましたが、成功しませんでした。

最後に、ここで例を挙げます http://blog.respondify.se/2011/09/using-dijit-tree-with-the-new-dojo-object-store/

この簡単なページを作成しました (dojotolkit 1.7.2 を使用しています)。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Tree Model Explorer</title>

<script type="text/javascript">
djConfig = {
parseOnLoad : true,
isDebug : true,
}
</script>
<script type="text/javascript" djConfig="parseOnLoad: true"
src="lib/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.Tree");
dojo.require("dojo.store.JsonRest");
dojo.require("dojo.data.ObjectStore");
dojo.require("dijit.tree.ForestStoreModel");

dojo.addOnLoad(function() {

var objectStore = new dojo.store.JsonRest({
target : "test.json",
labelAttribute : "name",
idAttribute: "id"
});

var dataStore = new dojo.data.ObjectStore({

objectStore : objectStore
});

var treeModel = new dijit.tree.ForestStoreModel({
store : dataStore,
deferItemLoadingUntilExpand : true,
rootLabel : "Subjects",
query : {
"id" : "*"
},
childrenAttrs : [ "children" ]
});

var tree = new dijit.Tree({
model : treeModel
}, 'treeNode');
tree.startup();
});
</script>
</head>
<body>

<div id="treeNode"></div>
</body>
</html>

私の休息サービスは次のjsonに応答します

{
data: [
{
"id": "PippoId",
"name": "Pippo",
"children": []
},
{
"id": "PlutoId",
"name": "Pluto",
"children": []
},
{
"id": "PaperinoId",
"name": "Paperino",
"children": []
}
]}

次の応答も試しました(実際、私の最終的な意図は、ツリーに遅延読み込みを使用することです)

{ data: [
 {
  "id": "PippoId",
  "name": "Pippo",
  "$ref": "author0",
  "children": true
 },
 {
  "id": "PlutoId",
  "name": "Pluto",
  "$ref": "author1",
  "children": true
 },
 {
  "id": "PaperinoId",
  "name": "Paperino",
  "$ref": "author2",
  "children": true
 }
]}

どちらも機能しません。firebug にエラー メッセージが表示されません。ページにルート「件名」が表示されるだけです。何らかの形で助けてくれる人に感謝します。

4

1 に答える 1

14

一見すると、

サーバーサイドが間違ったデータを返します。dojo リファレンス ガイドのクイックスタートjsonrest を次に示します。GET 部分に従ってください。

REST リクエストがどのように見えるか (ブラウザーからの GET) の方法により、サーバー側は 1) アイテムの配列を返すか、2) アイテムを返す必要があるため、違いがあります。

次のようにデータキーを削除してみてください。

[
  {
    "id": "PippoId",
    "name": "Pippo",
    "children": []
  }, {
    "id": "PlutoId",
    "name": "Pluto",
    "children": []
  }, {
    "id": "PaperinoId",
    "name": "Paperino",
    "children": []
  }
]

では、これはまだ遅延読み込み機能を提供しないのでしょうか? これは、コードのサンプルでモデルが非常に複雑な設定をしているためであるに違いありません。最初に REST store、次に OBJECT another store、次に ForestTree model、最後に Treeviewです。モデルがストアに提供するものを実装するのは非常に簡単で、二重ストアの定義は省略します。それ以外の場合、objectstore.query は reststore.query を呼び出しますが、これが機能するかどうかは完全にはわかりません。

にロジックがありませんRestStore

Treeには、データをツリーとしてレンダリングするための 5 つのモデル メソッドが必要です。

  1. getIdentity(object)- ストアによって既に提供されており、通常は再実装する必要はありません。
  2. mayHaveChildren(object)- オブジェクトに子があるかどうかを示します (実際に子をロードする前に)。この例では、「子」プロパティの存在を、子を持つことを示すものとして扱います。
  3. getChildren(parent, onComplete, onError)- 子を取得するために呼び出されます。これは非同期的に実行される可能性があり、終了時に onComplete コールバックを呼び出す必要があります。この例では、get() を実行して親オブジェクトの完全な表現を取得し、子を取得します。親が完全に読み込まれると、親から「子」配列が返されます。
  4. getRoot(onItem)- ルート ノードを取得するために呼び出されます。onItem コールバックは、ルート オブジェクトで呼び出す必要があります。この例では、ルート オブジェクトの ID/URL が「root」のオブジェクトを get() します。
  5. getLabel(object)- オブジェクトのラベルを返します (これは、ツリー内のノードの横に表示されるテキストです)。この例では、ラベルはオブジェクトの「名前」プロパティです。

これはどのように行うことができますか?いくつかの定義を作成しましょう:
1)サーバーはjsonrest.target「ベース」、ID「ルート」を 設定し、 2)サーバーは常に「子」キーを返し、存在する場合は true

var reststore = JsonRest({
    target:"data/",         // << adapt URL
    mayHaveChildren: function(object){
        // if true, we might be missing the data, false and nothing should be done
        return "children" in object;
    },
    getChildren: function(object, onComplete, onError){
        // this.get calls 'mayHaveChildren' and if this returns true, it will load whats needed, overwriting the 'true' into '{ item }'
        this.get(object.id).then(function(fullObject){
            // copy to the original object so it has the children array as well.
            object.children = fullObject.children;
            // now that full object, we should have an array of children
            onComplete(fullObject.children);
        }, function(error){
            // an error occurred, log it, and indicate no children
            console.error(error);
            onComplete([]);
        });
    },
    getRoot: function(onItem, onError){
        // get the root object, we will do a get() and callback the result
        this.get("root").then(onItem, onError);
    },
    getLabel: function(object){
        // just get the name (note some models makes use of 'labelAttr' as opposed to simply returning the key 'name')
        return object.name;
    }
});

カスタマイズされた RestStore をモデルとして Tree を作成する

上記で定義した変数 reststore を使用し、これをツリー構造パラメーターのモデルとして設定するだけです。

var tree = new dijit.Tree({
  model : treeModel
}, 'treeNode');
tree.startup();

サーバー側の遅延読み込み JSON データのセットアップ

子配列のほとんどのデータを除外すると、送信されるペイロードを減らすことができ、遅延読み込みを利用できます。受け取った 1 つのアイテム (例: /data/parents/number1parent) ごとに、アイテム自体の完全な表現を入力する必要があります。子供がいる場合は、1) 取得labelsするためにこれらに名前を付ける必要があります。 view「name」を使用します。キー、getLabel メソッドを参照してください。2) 一意の ID を指定し、3) 子を持つかどうかを示します。

ルート JSON

{
    "name": "Papparazis",
    "id": "root",
    "children": [
  {
    "id": "PippoId",
    "name": "Pippo",
    // may have children - makes dijit.Tree create expandoNode and events
    "children": true
  }, {
    // example leaf, children == undefined
    "id": "PlutoId",
    "name": "Pluto" 
  }, {
    "id": "PaperinoId",
    "name": "Paperino",
    "children": true
  }
]
}

これで、
ROOT
+ Pippo
* Pluto
+ Paperinoを表示します

任意のアイテム JSON

Pippo をクリックして彼の子オブジェクトを表示したい場合は、回帰してみましょう。ツリー リクエスト ターゲットtreeNode.item.childrenは、設計上、RestStore で object.id==PippoId のリクエストに変換されます。URL は、this.target/object.parent-relations/object.idshcema を使用してコンパイルされます。この場合、サーバーはdata/PippoIDGET を介して最終的な URL の完全な表現で応答します。

{
    "name": "Pippo",
    "id": "PippoId",
    "surname" : "foo",
    "shoosize" : "bar",
    "children": [
        {
            "name": "Baz",
            "id": "BazId"
        }, {
            "name": "Godfather",
            "id": "GodfatherId",
            "children": true
        }
    ]
}

「完全な表現オブジェクト」(最上位レベル)には追加のエンティティが含まれていることに注意してください。たとえば、shoosize と surname です。ただし、子は依然として「短い形式の表現オブジェクト」です。

サーバーサイド PHP Rest 実装

したがって、議論のために、PHP で残りの機能を実装する方法を以下に示します。papparazies は sql-db のテーブルであり、データ列を取得するためgetPaparazi($id)に withgetPapasKids($id)関数が実装されていると仮定します。

まず、.htaccess の変更によって、これを処理する方法を apache に伝える必要があります。これに慣れていない場合は、次のリソースのいくつかを確認してください。

これを /.htaccess に入れます。'/' は DocumentRoot であり、必要に応じて RewriteBase を変更します。

<IfModule mod_rewrite.c>
  RewriteEngine on
  # If your site is running in a VirtualDocumentRoot at http://example.com/,
  # uncomment the following line:
  # RewriteBase /
  # If no file nor a directory exists for the request url,
  # rewrite URLs of the form 'data/object' to the form 'index.php?rest=data/object'.

  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ index.php?rest=$1 [L,QSA]

</IfModule>

PHP の index.php (存在しないすべてのファイル要求のハンドラーを書き直したもの) の観点から、次のように簡単に作成できます。

<?php

 if(isset($_REQUEST['rest'])) {

   // IMPORTANT; validate the request, e.g. check for referrer or similar

   $ids = explode("/", $_REQUEST['rest']);
   $pathCount = count($ids);
   $table = array_shift($ids); // as string, 'data/' by example
   if(!$table || $table == "") exit; //  ... validate more
   if($pathCount > 1) {
      $objectRequested = array_pop($ids); // as string '' for root
   }
   if($pathCount > 2) {
      $mid = $ids; // an array, holding rest of the path (middle relatives)
   }
   // with this in hand, we should be able to get the object. 
   // by example we're serving store data for paparazies which 
   // has the 'target' parameter set to 'data/'
   if($table == "data") {
      $fields = getPaparazi($objectRequested);
      $obj = new stdobject();
      $obj->name = $fields['name'];
      $obj->id = $objectRequested;
      $obj->shoosize = $fields['shoosize'];
      $obj->children = array();
      if( ( $children = getPapasKids($objectRequested) ) ) {
          foreach($children as $child) {
             $c_obj = new stdobject();
             $c_obj->name = $child['name'];
             $c_obj->id = $child['id'];
             if($child['hasChildren']) 
                $c_obj->children = true;
             $obj->children[] = $c_obj;
          }
      }
      header("Content-Type: application/x-json; charset=XXXXX");
      print json_encode($obj);
      flush();
      exit;
   }
 }
?>

レストストアとツリーに関するまとめられた情報については、 SitePen ブログを参照してください。

于 2012-05-31T10:37:47.957 に答える