2015-12-21 44 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模式作为服务,现在它可以工作。