2017-04-25 59 views
3

我試圖創建一個指令,允許我傳入一個屬性字符串,然後在訂閱事件時將其用作「name」參數使用$ scope。$ on。本質上,這一系列事件是這樣的:

  1. 一個對象被廣播使用$ rootScope。$ broadcast在另一個控制器中調用'validationResultMessage'。
  2. 我有一個指令,其中有一個屬性叫「訂閱」,我傳遞字符串'validationResultMessage'。
  3. 該指令將「subscription」屬性的值傳遞給其作用域,並使用「$ 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

我打算髮布我的答案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

是的,'$ broadcast'給'$ root'並讓任何訂閱的偵聽器獲得事件。在這個要求中,我們通過指令來做到這一點,每一個細節帕恩只應該聽取它訂閱的內容。需要可重複使用和獨立。 'selected-item'是當收到消息時需要更新的'model',可能綁定到聲明的控制器/視圖。對於這種類型的DOM操作以及需要指令邏輯的'link'是強大的。我已經使用'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

嗯,我看你是想在這裏做什麼,我想這可能是問題的一部分,但是實施這個沒有用。現在看起來我的$ $從來沒有被擊中。 – istrupin

2

所以另一種方式,我設法解決這個具體問題是隻使用內部DetailPaneController在指令體定義。我的部分問題是,我讓控制器作爲父控制器在我的html中使用ng-controller=以及在指令主體中定義兩次被實例化。這樣我就可以使用直接的「@」綁定,並且所有內容都按照正確的順序解決。我甚至可以在我的模板中有另一個指令,我可以將我的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> 

相關問題