0

これを特定のDOM要素(サードパーティのライブラリによって動的に作成されたDOM)に挿入するコンポーネントを動的にコンパイルしたいと思います。 したがって、私は$compile,$scopeを使用します。

https://jsbin.com/gutekat/edit?html,js,console,output

// ListController $postLink life cycle hook 

function $postLink() { 
    ... 

    $timeout(function() { 
    ctrl.items.splice(0, 1); 
    $log.debug('First item of array is removed'); 
    $log.debug(ctrl.items); 
    }, 2000); 
} 

が、ListItemController$onChangesライフサイクルフック以下は実行されません。

// ListItemController $onChanges life cycle hook 

function $onChanges(changes) { 
    if (!changes.item.isFirstChange()) { 
    $log.debug(changes); // Not executed 
    } 
} 

私はitemListItemController前にコントローラのインスタンスの初期化を渡すangular.mergeが主な原因であると推測します。

var itemScope = $scope.$new(true, $scope); 
itemScope = angular.merge(itemScope, { 
    $ctrl: { 
    item: item 
    } 
}); 
+0

$ onChanges item'はそれに対する変更は、$ onChanges機能を起動しません、あなたは$の代わりに時計を使用する必要があり、結合していない 'だけなので、あなたがバインディングに入れプロパティに耳を傾けます。 –

+0

@AnthonyC次に、 'ListController'のコンパイル時に、' item'オブジェクトを 'listItem'コンポーネントバインディングに正しく渡す方法はありますか? – taehwanno

答えて

1

片方向バインディングで何が起こっているかを示すためにコードを少し修正しました。

angular.module('app', [ 
    'list.component', 
    'list-item.component' 
]); 

/** 
* list.component 
*/ 
angular 
    .module('list.component', []) 
    .component('list', { 
     controller: ListController, 
     template: '<div id="list"></div>' 
    }); 

ListController.$inject = ['$compile', '$document', '$log', '$scope', '$timeout']; 
function ListController($compile, $document, $log, $scope, $timeout) { 
    var ctrl = this; 

    ctrl.$onInit = $onInit; 
    ctrl.$postLink = $postLink; 

    function $onInit() { 
     ctrl.items = [ 
      { 
       id: 0, 
       value: 'a' 
      }, 
      { 
       id: 1, 
       value: 'b' 
      }, 
      { 
       id: 2, 
       value: 'c' 
      } 
     ]; 
    } 

    function $postLink() { 
     var index = 0; 
     // Not entirely sure what you need to do this. This can easily be done in the template. 
     /** ie: 
     * template: '<div id="list" ng-repeat="item in $ctrl.items"><list-item item="item"></list-item></div>' 
     **/ 

     var iElements = ctrl.items.map(function (item) { 
      var template = '<list-item item="$ctrl.items[' + (index) + ']"></list-item>'; 
      index++; 
      // you don't want to create an isolate scope here for the 1 way binding of the item. 
      return $compile(template)($scope.$new(false)); 
     }); 

     var listDOM = $document[0].getElementById('list'); 
     var jqListDOM = angular.element(listDOM); 

     iElements.forEach(function (iElement) { 
      jqListDOM.append(iElement); 
     }); 

     $timeout(function() { 
      // this will trigger $onChanges since this is a reference change 
      ctrl.items[0] = { id: 3, value: 'ss' }; 
      // this however, will not trigger the $onChanges, if you need to use deep comparison, consider to use $watch 
      ctrl.items[1].value = 's'; 
      ctrl.items[2].value = 's'; 
     }, 2000); 
    } 
} 

/** 
* list-item.component 
*/ 
angular 
    .module('list-item.component', []) 
    .component('listItem', { 
     bindings: { 
      item: '<' 
     }, 
     controller: ListItemController, 
     template: '<div class="listItem">{{ $ctrl.item.value }}</div>' 
    }); 

ListItemController.$inject = ['$log']; 
function ListItemController($log) { 
    var ctrl = this; 

    ctrl.$onChanges = $onChanges; 

    function $onChanges(changes) { 
     if (!changes.item.isFirstChange()) { 
      $log.debug(changes); // Not executed  
     } 
    } 
} 
関連する問題