2015-12-21 50 views
0

我在理解$作用域傳播的工作原理時遇到了一個問題。 我有2個嵌套控制器:AngularJS作用域的傳播

<div ng-controller="ClientCtrl"> 
    <div class="table-responsive" ng-init="getSocietes()"> 

    <div style="width: 98%; height: 500px;" ag-grid="gridSocietes" class="ag-blue ag-basic"> 

    </div> 

    </div> 
    <div ng-controller="PopupCtrl"> 
     <script type="text/ng-template" id="pmoPopupConfirmDelete.html"> 
    <div class="modal-header"> 
     <h3 class="modal-title">I'm a modal!</h3> 
    </div> 
    <div class="modal-body"> 
     <ul> 
      <li ng-repeat="item in items"> 
       <a href="#" ng-click="$event.preventDefault(); selected.item = item">{{ item }}</a> 
      </li> 
     </ul> 
     Selected: <b>{{ selected.item }}</b> 
    </div> 
    <div class="modal-footer"> 
     <button class="btn btn-primary" type="button" ng-click="ok()">OK</button> 
     <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button> 
    </div> 
</script> 
    </div> 
</div> 

第一控制器具有AG-網格在它的一些數據。當用戶點擊刪除按鈕時,我需要顯示一個彈出窗口,以便讓他確認刪除表格中的一行。

我正在嘗試使用Angular UI Modal控制器,因爲它在主頁中顯示。

因此,我有這2個控制器:

var myApp = angular.module('myApp'); 

myApp.controller('SocietesController', ['$scope', '$http', '$location', '$routeParams', function($scope, $http, $location, $routeParams){ 

$scope.gridSocietes = { 

    columnDefs: [ 
     {headerName: "", field: "", width: 45, suppressSorting: true, suppressResize: true, suppressMenu: true, cellRenderer: actionCellRenderer, suppressSizeToFit: true}, 
     {headerName: "Société", field: "Societe", cellRenderer: societeCellRenderer, sort: 'asc', filter: 'text'}, 
     {headerName: "Adresse", field: "Adresse_1", cellRenderer: adresseCellRenderer, filter: 'text'}, 
     {headerName: "Code postal", field: "CP", width: 100, suppressSizeToFit: true, filter: 'text'}, 
     {headerName: "Ville", field: "Ville", filter: 'text'}, 
     {headerName: "Tel", field: "Tel", width: 120, suppressSizeToFit: true, filter: 'text'}, 
     {headerName: "Fax", field: "Fax", width: 120, suppressSizeToFit: true, filter: 'text'}, 
     {headerName: "E-mail", field: "Email", filter: 'text'}, 
     {headerName: "Site Web", field: "Site_Web", filter: 'text'}, 
     {headerName: "Utilisateurs", width: 100, cellRenderer: usersCellRenderer, suppressSorting: true, suppressResize: true, suppressMenu: true, suppressSizeToFit: true} 

    ], 
    enableColResize: true, 
    enableSorting: true, 
    enableFilter: true, 
    rowSelection: 'single', 
    rowData: null, 
    angularCompileRows: true 
}; 

$scope.getSocietes = function(){ 
    $http.get('/api/societes').success(function(response){ 
     $scope.societes = response; 
     $scope.gridSocietes.api.setRowData(response); 
     $scope.gridSocietes.api.sizeColumnsToFit(); 
    }); 
} 

$scope.supprimerSociete = function(id, index){ 
    console.log($scope) 
    alert('go'); 
    openPopup('sm', 'pmoPopupConfirmDelete.html') 
    return; 
    $http.delete('/api/societes/'+id).success(function(response){ 
     $scope.societes.splice(index, 1); 
     $scope.gridSocietes.api.setRowData($scope.societes); 
    }); 
} 

console.log($scope) 

}]); 

且彈出式控制器:

var myApp = angular.module('myApp'); 

myApp.controller('PopupCtrl', ['$scope', function ($scope, $uibModal, $log) { 
$scope.items = ['item1', 'item2', 'item3']; 

$scope.animationsEnabled = true; 

$scope.openPopup = function (size, template) { 

var modalInstance = $uibModal.open({ 
    animation: true, 
    templateUrl: 'pmoPopupConfirmDelete.html', 
    controller: 'ModalPopupCtrl', 
    size: size, 
    resolve: { 
    items: function() { 
     return $scope.items; 
    } 
    } 
}); 

modalInstance.result.then(function (selectedItem) { 
    $scope.selected = selectedItem; 
}, function() { 
    $log.info('Modal dismissed at: ' + new Date()); 
}); 
}; 

$scope.toggleAnimation = function() { 
    $scope.animationsEnabled = !$scope.animationsEnabled; 
}; 

}]); 


// Please note that $modalInstance represents a modal window (instance) dependency. 
// It is not the same as the $uibModal service used above. 

myApp.controller('ModalPopupCtrl', function ($scope, $uibModalInstance, items) { 

$scope.items = items; 
$scope.selected = { 
    item: $scope.items[0] 
}; 

$scope.ok = function() { 
    $uibModalInstance.close($scope.selected.item); 
}; 

$scope.cancel = function() { 
    $uibModalInstance.dismiss('cancel'); 
}; 
}); 

我試圖理解爲什麼在第一控制器$ scope.supprimerSociete功能不請參閱第二個控制器中的OpenPopup功能。

我已經嘗試了很多東西,但OpenPopup函數從未出現在第一個控制器的範圍中(即使我嘗試使用$ scope.OpenPopup調用它),而來自第一個控制器的所有內容都顯示在Popup控制器當我登錄$範圍內...

我在那裏失蹤?

Thx提前!

+1

childScope繼承父級的功能,但父級不知道他的子級的功能。 – Pjetr

回答

0

你可以通過你的項目$uibModal開放過程中刪除與決心,那麼你就可以回傳給此項目密切的承諾。

有了這個如果yes被點擊,你可以在靠近回調刪除該項目。要看到這個動作,請看下面的演示或在fiddle

很難明白爲什麼你的代碼是不工作,因爲我看不到的supprimerSociete通話,以及如何加入你的控制器。我只能猜測,範圍是這樣的:

  • SocietesController(父範圍)
    • ClientCtrl(孩子)
      • popupCtrl(ClientCtrl兒童)

然後如果你想使用$ sco pe客戶端控件或PopupCtrl的方法,他們當然不在那裏,因爲父母不會繼承孩子的任何東西。請閱讀更多關於scopes和約scope inheritance

也正因爲沒有這樣的方法,你的方法調用openPopup看起來很奇怪。如果你在$scope上定義了一個方法,它必須像這樣調用$scope.openPopup()(如果它在$ scope中是可用的)。

如果你想彈出可重用,我會爲它創建一個工廠,那麼你可以依賴注入你需要它的地方。

angular.module('demoApp', ['ui.bootstrap']) 
 
.controller('MainController', function ($scope, $uibModal, $log) { 
 

 
    $scope.items = ['item1', 'item2', 'item3']; 
 

 
    $scope.animationsEnabled = true; 
 

 
    $scope.delete = function (item) { 
 
\t \t console.log('del', item); 
 
    var modalInstance = $uibModal.open({ 
 
     animation: $scope.animationsEnabled, 
 
     templateUrl: 'myModalContent.html', 
 
     controller: 'ModalInstanceCtrl', 
 
     size: 'lg', 
 
     resolve: { 
 
     /*items: function() { 
 
      return $scope.items; 
 
     },*/ 
 
     item: function() { 
 
     \t // pass item to delete 
 
      return item; 
 
     } 
 
     } 
 
    }); 
 

 
    modalInstance.result.then(function (deleteItem) { 
 
     var index = $scope.items.indexOf(deleteItem); 
 
     
 
     $scope.items.splice(index,1); 
 
    }, function() { 
 
     $log.info('Modal dismissed at: ' + new Date()); 
 
    }); 
 
    }; 
 

 
    $scope.toggleAnimation = function() { 
 
    $scope.animationsEnabled = !$scope.animationsEnabled; 
 
    }; 
 

 
}); 
 

 
// Please note that $modalInstance represents a modal window (instance) dependency. 
 
// It is not the same as the $uibModal service used above. 
 

 
angular.module('demoApp').controller('ModalInstanceCtrl', function ($scope, $uibModalInstance, item) { 
 

 
\t $scope.item = item; 
 
    
 
    $scope.ok = function() { 
 
    $uibModalInstance.close($scope.item); 
 
    }; 
 

 
    $scope.cancel = function() { 
 
    $uibModalInstance.dismiss('cancel'); 
 
    }; 
 
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script> 
 

 
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" 
 
rel="stylesheet"/> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.14.3/ui-bootstrap-tpls.min.js"></script> 
 

 
<div ng-app="demoApp" ng-controller="MainController"> 
 
    <script type="text/ng-template" id="myModalContent.html"> 
 
     <div class="modal-header"> 
 
      <h3 class="modal-title">Confirm delete</h3> 
 
     </div> 
 
     <div class="modal-body"> 
 
      Are you sure to delete {{item}}? 
 
     </div> 
 
     <div class="modal-footer"> 
 
      <button class="btn btn-primary" type="button" ng-click="ok()">Yes</button> 
 
      <button class="btn btn-warning" type="button" ng-click="cancel()">No</button> 
 
     </div> 
 
    </script> 
 
    
 
    <ul> 
 
     <li ng-repeat="item in items"> 
 
     {{item}} 
 
     <button ng-click="delete(item)"> 
 
      delete... 
 
     </button> 
 
     </li> 
 
    </ul> 
 
</div>

0

一個childScope繼承父的功能,但家長不知道自己的孩子的功能。

你應該使用更多的文件來達到這個目的。首先開始使用指令,並將您的函數/變量定義爲控制器的公共成員。 如果你已經這樣做了,你會立即明白邏輯有缺陷的地方:clientCtrl.openPopup();本質上就是你嘗試過的。

其次,separation of concerns,所有的業務邏輯應該轉移到服務。控制器不應該處理API請求,它只需要從服務請求數據並顯示它,並處理所有的DOM事件。就這樣。

clientCtrl.openPopup(items) 
    > PopupService.openPopup(items); 

popupCtrl.opened = PopupService.opened; 
popupCtrl.items = PopupService.items; 
0

感謝您的回答。

正如@Pjetr所建議的那樣,在Dan Wahlin的Github頁面的幫助下,我使用了angular.ui模式作爲服務,現在它可以工作。