2017-04-25 14 views
3

イベントにサブスクリプションするときに属性名として渡すことができるディレクティブを作成しようとしています。 $ scope。$ onを使用しています。基本的に、一連のイベントこれです:。

  1. オブジェクトは、例えば、他のコントローラでは、「validationResultMessage」と呼ばれる$ rootScopeを使用して放送$放送されています。
  2. 私は、 "subscriptionResultMessage"という文字列を渡す "subscription"という属性を持つディレクティブを持っています。
  3. このディレクティブは、 "サブスクリプション"属性の値をスコープに渡し、 "$ scope。$ on"でサブスクリプションを行います。

問題は、すべてが評価された時点で属性の値が "未定義"であるように見えるため、$ scope。$ onを使用して購読しようとすると、実際には "undefined "ではなく "

" validationResultMessageここに私のディレクティブです:

私は、このように使用
app.directive('detailPane', function() { 
return { 
    restrict: 'E', 
    scope: { 
     selectedItem: '=', 
     subscription: '@', 
    }, 
    templateUrl: 'app/templates/DetailPane.html', //I'm also worried that this is causing my controller to get instantiated twice 
    controller: 'DetailPaneController' 

    }; 
}); 

<td class="sidebar" ng-controller="DetailPaneController" ng-style="{ 'display': sidebarDisplay }"> 
      <detail-pane 
        selected-item='validationResult' 
        subscription='validationResultMessage'/> 

</td> 

そして、私はにこの属性を渡すようにしようとしているコントローラ:

app.controller('DetailPaneController', ['$scope', '$http', 'dataService', 'toastr', '$uibModal', '$rootScope', '$attrs', function ($scope, $http, dataService, toastr, $uibModal, $rootScope, $attrs) { 
$scope.fetching = []; 
$scope.validationResult = null; 
$scope.sidebarDisplay = 'block'; 



console.log('subscription is ', $scope.subscription); 
var thisSubscription = $scope.subscription; 

//if I hardcode the param as 'validationResultMessage', this works 
$scope.$on($scope.subscription, function (event, arg) { 
    $scope.validationResult = arg; 
    }); 
}]); 

答えて

1

私はそれがコードのビットだことを考えると、私の答えの第一を投稿するつもりです、これは必須の結果であるなら、私に知らせて、私はコメントを提供することができますしてください。提供されたコードスニペットを実行できるはずです。

var app = angular.module('myApp', []); 
 

 
app.directive('detailPane', function() { 
 
    return { 
 
    restrict: 'E', 
 
    transclude: false, 
 
    scope: { 
 
     selectedItem: '=', 
 
     subscription: '@' 
 
    }, 
 
    link: function(scope, elem, attr) { 
 
     scope.$on(scope.subscription, function(e, data) { 
 
     scope.selectedItem = data.result; 
 
     elem.text(data.message); 
 
     }); 
 
    }, 
 
    }; 
 
}); 
 

 
app.controller('DetailPaneController', function($scope) { 
 
    $scope.validationResult1 = ""; 
 
    $scope.validationResult2 = ""; 
 
}); 
 

 
app.controller('SecondController', function($rootScope, $scope, $timeout) { 
 

 
    $timeout(function() { 
 
    $rootScope.$broadcast('validationResultMessage1', { 
 
     message: 'You fail!', 
 
     result: 'Result from 1st fail' 
 
    }) 
 
    }, 2000); 
 

 
    $timeout(function() { 
 
    $rootScope.$broadcast('validationResultMessage2', { 
 
     message: 'You also fail 2!', 
 
     result: 'Result from 2nd fail' 
 
    }) 
 
    }, 4000); 
 

 
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script> 
 

 
<body ng-app='myApp'> 
 
    <div ng-controller="DetailPaneController"> 
 
    <detail-pane class='hello' selected-item='validationResult1' subscription='validationResultMessage1'></detail-pane> 
 
    <br/> 
 
    <detail-pane class='hello' selected-item='validationResult2' subscription='validationResultMessage2'></detail-pane> 
 

 
    <hr/> 
 
    <span>{{validationResult1}}</span> 
 
    <br/> 
 
    <span>{{validationResult2}}</span> 
 

 
    </div> 
 
    <div ng-controller="SecondController"> 
 

 
    </div> 
 
</body>

+1

これは本当に私が後にしている行動を提供しています。私が正しく理解している場合、親DetailPaneControllerのスコープのvalidationResultをSecondControllerによってブロードキャストされているものに設定しています。私は次に、私が補間インラインをしたくない場合、どのようにしたいかについての情報を表示するために、validationResult1とvalidationResult2を参照するテンプレートを使用することができると仮定します。 この動作を達成するためにリンク関数を使用していますが、これは前に考えたことではありません。このソリューションの基本的な仕組みを正しく理解していますか? – istrupin

+1

はい、 '$ root'に' $ broadcast'を送り、購読しているリスナーにイベントを渡させます。この要件では、ディレクティブでこれを行い、各detailsPaneはそれが購読しているものだけを聞くべきです。再利用可能で独立している必要があります。 'selected-item'はメッセージが受信されたときに更新される必要のある' model'です。おそらく宣言されたコントローラ/ビューにバインドされます。 'link'はこの種のDOM操作や、指示ロジックが必要なときには強力です。私は 'validationresult1'と2を使って設定を模倣し、詳細を渡すことができることを示しました。それは必須ではありません。@ istrupin – Searching

0

私はあなたが$ scope.subscriptionにウォッチャを設定し、新しい値が設定されているかどうかをチェックしてから渡されたイベントをサブスクライブ開始すべきだと思います。

$scope.$watch('subscription', function(nv, ov){ 
//this makes sure it won't trigger at initialization 
if(nv!==ov){ 
    $scope.$on($scope.subscription, function (event, arg) { 
     $scope.validationResult = arg; 
    }); 
} 
}); 
+0

うーん、私はあなたがここで何をしようとして見て、私はそれが問題の一部であるかもしれないと思います、それを実装することはできませんでした。今の私のように見える$ onは決して打撃を受けません。 – istrupin

2

だから私は、この特定の問題を解決するために管理し、別の方法は、ディレクティブ体で定義された内部DetailPaneControllerのみを使用することです。私の問題の一部は、コントローラーを私のhtmlにng-controller=を使用している親コントローラーとディレクティブ本文に定義しているので、コントローラーを2回インスタンス化することになりました。このようにして、単純な "@"バインディングを使用するだけで、すべてが正しい順序で解決されます。私は私のvalidationResultを渡すことができる私のテンプレート内の別の指示をすることができます。

新しいセットアップは次のようになります。

DetailPaneController:

app.controller('DetailPaneController', ['$scope', '$http', function ($scope, $http) { 

$scope.$on($scope.subscription, function (event, arg) { 
    $scope.validationResult = arg; 
    $scope.exception = JSON.parse(arg.Exception); 
    }); 
}]); 

DetailPane指令:

app.directive('detailPane', function() { 
return { 
    restrict: 'E', 
    scope: { 
     subscription: '@' //notice I am no longer binding to validationResult 
    }, 
    templateUrl: 'app/templates/DetailPane.html', 
    controller: 'DetailPaneController' 
    }; 
}); 

指令をHTMLで使用されます(良い測定用)

 <div class="sidebar" ng-style="{ 'display': sidebarDisplay }"> <detail-pane subscription='validationResultMessage' /> </div> 

指令テンプレート:

<div class="well sidebar-container"> 
<h3>Details</h3> 
<div ng-show="validationResult == null" style="padding: 15px 0 0 15px;"> 
    <h5 class=""><i class="fa fa-exclamation-triangle" aria-hidden="true" /> Select a break to view</h5> 

</div> 
<div ng-show="validationResult != null"> 
    <table class="table table-striped"> 
     <tr ng-repeat="(key, value) in validationResult"> 
      <td class="sidebar-labels">{{key | someFilter}}</td> 
      <td >{{value | someOtherFilter : key}}</td> 
     </tr> 
    </table> 
    <another-directive selected-item="validationResult" endpoint="endpoint" /> 
</div> 

関連する問題