2016-02-05 15 views
9

私は開始ビューブロックであるためにhttp://codepen.io/bachly/pen/KwWrzGにtreeviewディレクティブクレジットを持っています。コレクションにオブジェクトを追加するときに更新しようとしています。私はオブジェクトを更新して新しいオブジェクトを挿入できますが、$scopedアイテムが更新されるとtreeviewディレクティブは呼び出されません。 最終的に使用されるデータは、現時点でサービスから取得されます。私は模擬データでテストしています。新しいオブジェクトがコレクションに追加されたときにangle treeviewディレクティブを更新する

元のコレクションは、この

$scope.myList = { 
      children: [ 
       { 
        name: "Event", 
        children: [ 
        { 
         name: "Event Date", 
         parent:"Event", 
         children: [ 
          { 
           name: "2008", 
           filterType: '_eventStartDate', 
           parent: 'Event' 
          }, 
          { 
           name: "2009", 
           filterType: '_eventStartDate', 
           parent: 'Event' 
          } 
         ] 
        }, 
        { 
         name: "Event Attendee", 
         parent: "Event", 
         children: [ 
          { 
           name: "Person 1", 
           filterType: '_eventAttenddeeName', 
           parent: 'Event Attendee' 
          }, 
          { 
           name: "Person 2", 
           filterType: '_eventAttenddeeName', 
           parent: 'Event Attendee' 
          } 
         ] 
        } 
        ] 
       }] 
    }; 


    var TheOtherCollection = { 
     children: [ 
     { 
      name: "A New Event", 
      children: [ 
       { 
        name: "The Other Date", 
        parent: " A New Event", 
        children: [ 
        { 
         name: "2010", 
         FilterType: '_eventStartDate', 
         Parent: '_event' 
        }, 
        { 
         name: "2011", 
         FilterType: '_eventStartDate', 
         Parent: '_event' 
        } 
        ] 
       } 
      ] 
     }] 
    }; 

これは、次のディレクティブを使用してチェックボックスやHTML

app.directive('tree', function() { 
    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      t: '=src', 
      filter: '&' 
     }, 
     controller: 'treeController', 
     template: '<ul><branch ng-repeat="c in t.children track by $index" src="c" filter="doSomething(object, isSelected)"></branch></ul>' 
    }; 
}); 

app.directive('branch', function($compile) { 

    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      b: '=src', 
      filter: '&', 
      checked: '=ngModel' 
     }, 

      template: '<li><input type="checkbox" ng-click="innerCall()" ng-model="b.$$hashKey" ng-change="stateChanged(b.$$hashKey)" ng-hide="visible" /><a>{{ b.name }}</a></li>', 
      link: function (scope, element, attrs) { 

       var clicked = ''; 
       var hasChildren = angular.isArray(scope.b.children); 
       scope.visible = hasChildren; 
       if (hasChildren) { 
        element.append('<tree src="b"></tree>'); 
        $compile(element.contents())(scope); 
       } 
       element.on('click', function(event) { 
        event.stopPropagation(); 
        if (hasChildren) { 
         element.toggleClass('collapsed'); 
        } 
       }); 
       scope.stateChanged = function(b) { 
        clicked = b; 
       }; 

       scope.innerCall = function() { 
        scope.filter({ object: scope.b, isSelected: clicked }); 
       }; 
      } 
     }; 
    }); 

し、HTML

<div ng-controller="treeController"> 
     <tree src="myList" iobj="object" filter="doSomething(object, isSelected)"></tree> 

     <a ng-click="clicked()"> link</a> 
    </div> 

と、ツリービューを作成するようになります。チェックボックスをクリックすると、新しいコレクションがlodaを使用して既存のコレクションに追加されますshjs

新しい配列を作成し、子どもたちのアレイ内にそれを追加しますNG-クリックイベントが

$scope.doSomething = function (object, isSelected) { 
    if (isSelected) { 
     var item = object; 
     console.log(item); 
     nestAssociation(object, $scope.myList, TheOtherCollection); 
    } 
} 

function nestAssociation(node, oldCollection, newAggregates) { 
    // var item = fn(oldCollection, node.parent); 
    var updatedArray = _.concat(oldCollection.children, newAggregates); 
    console.log(updatedArray); 
    if (updatedArray != null) 
     updateMyList(updatedArray); 
} 

私は、「私は、新しいオブジェクトを持っていますが、私ができる出力を見ることができます更新するためにツリービューを取得しないでください。私はディレクティブ内でclickイベントに$ compile(element)を追加しようとしましたが、配列はまだ作成されていないので変更はありません。

このディレクティブに$ watchを追加する必要がありますか?そうであれば、新しいネストされたコレクションを再レンダリングして表示する指示を得ることができます。

更新

ここフィードバックや質問のいくつかの基本は、質問の周りにもう少し詳細です。私が見ている問題は、問題を取り巻くデータを移動する限り、配列が既存のモデルに追加された後にツリービューを再レンダリングすることはできません。 次のリンクis a working plunkerは、現在動作しているプロジェクトを示しています。私は、オブジェクトが更新されて参照しながらチェックボックスが enter image description here

を選択した後 が出力に私が見ることができるクロムのdevのツールを実行すると、モデルが更新され、ディレクティブは、オブジェクトに追加された新しい配列を示すように更新されません。これは私が理解を助ける必要がある部分です。事前に

おかげ

+1

実際の問題を確認してコードで作業できるplunkrやcodepenを作成できれば素晴らしいでしょう(私が理解しているように、リンクされたcodepenはちょうどあなたの出発点でした)。 –

+0

'nestAssociation()'によって呼び出される 'updateMyList'関数のコードを投稿できますか?私はこれがあなたが実際に '$ scope.myList'で更新された配列を保存する場所だと思います。 –

+1

私の質問をプランナーリンクで更新しました – rlcrews

答えて

4

を追加した後、あなたは(ベストプラクティスである)内部指令に関数を渡すが、あなたはscope.filterへのアクセス権を持っています。いいえdoSomethingFunction。これはundefinedです。

filter="doSomething(object, isSelected)"
=>
filter="filter(object, isSelected)"

app.directive('tree', function() { 
    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      t: '=src', 
      filter: '&' 
     }, 
     controller: 'treeController', 
     template: '<ul> 
        <branch ng-repeat="c in t.children track by $index"  
        src="c" filter="filter(object, isSelected)"> 
        </branch> 
        </ul>' 
    }; 
}); 

次へ:

彼らはプライベートなので、あなたは、angularJSで$$変数にアクセスすることはできません。たぶんあなたのDBから1つ作る必要があります...しかし、$$hashkeyは簡単な解決策と思われます。 ngModelは、あなたのツリーディレクティブのテンプレートに存在しないため、

checked属性は、エラーをスローする可能性があります。

チェックボックスはモデルとして$$ハッシュキーを持つことはできません。
Ng-changeとng-clickは常に同時に呼び出されますが、最も単純なものを使用してください。

app.directive('branch', function($compile) { 

    return { 
     restrict: 'E', 
     replace: true, 
     scope: { 
      b: '=src', 
      filter: '&' 
     }, 

      template: '<li><input type="checkbox" ng-click="innerCall(b.$$hashKey)" ng-model="isChecked" ng-hide="visible" /><a>{{ b.name }}</a></li>', 
      link: function (scope, element, attrs) { 

       scope.isChecked = false; 
       var hasChildren = angular.isArray(scope.b.children); 
       scope.visible = hasChildren; 
       if (hasChildren) { 
        element.append('<tree src="b"></tree>'); 
        $compile(element.contents())(scope); 
       } 
       element.on('click', function(event) { 
        event.stopPropagation(); 
        if (hasChildren) { 
         element.toggleClass('collapsed'); 
        } 
       }); 

       scope.innerCall = function(hash) { 
        if(scope.isChecked){ 
         scope.filter({ object: scope.b, isSelected: hash }); 
        } 

       }; 
      } 
     }; 
    }); 

UPDATE

あなたtreeディレクティブで、あなたindex.htmlビューで同じtreeControllerを持っています。 これは、ビューが更新されない原因です。

あなたの指示にあるものを削除しました。そうしないと、それぞれの子供用のコントローラが用意されます。
あなたのコントローラでは良いconsole.logメッセージが見えましたが、コントローラにはONE指令がありました。
index.htmlのコントローラにアクセスしていませんでした。

は、その後、私はチャイルズ間filter機能通信を固定:

あなたは新しいtree年代追加時にフィルタ機能を伝えるのを忘れて:あなたの親ディレクティブのテンプレートでも

element.append('<tree src="b" filter="filter({ object: object, isSelected: isSelected })"></tree>');

を、関数にパラメータを送るためにハッシュも必要です:
filter="filter({ object: object, isSelected: isSelected })"

上記のコメントでコードを変更せずにPlunker HEREを編集しました。
(私は何を書くことは、あなたが望むものではなく、あなたがコメントしなかったので、あなたがまだあなたのコードの高速をundertandので、私はむしろそれを変更していないかわからない)
しかし、ビューは現在更新しています!
私はあなたが望むものを少しデバッグし、上記のコメントで十分であると思います。 2

EDITあなたはプロパティchrildenでオブジェクトを返すのを忘れていました。あなたは問題を引き起こした配列を返しました。ここで

function updateMyList(data) { 
     var transformed = { children : data }; 
     $scope.myList = transformed; 
    } 

は作業PLUNKERです。

0

するTry $スコープ。$(適用)

+0

$ apply()または$ scope。$ apply(function(){...})は、関数が現在$ apply()サイクルに入っているので機能しません。それで新しいものを呼び出すことはできません – rlcrews

+1

@ricrews $ scopeoutにあなたの呼び出しをラップすることで、$ applyサイクルの問題を避けることができます。$ timeout呼び出しで$ apply – twsaef

関連する問題