ventanas - Problema de alcance en AngularJS usando AngularUI Bootstrap Modal
modal with angularjs (3)
plunker: http://plnkr.co/edit/wURNg8ByPYbEuQSL4xwg
example.js:
angular.module(''plunker'', [''ui.bootstrap'']);
var ModalDemoCtrl = function ($scope, $modal) {
$scope.open = function () {
var modalInstance = $modal.open({
templateUrl: ''modal.html'',
controller: ''ModalInstanceCtrl''
});
};
};
var ModalInstanceCtrl = function ($scope, $modalInstance) {
$scope.ok = function () {
alert($scope.text);
};
$scope.cancel = function () {
$modalInstance.dismiss(''cancel'');
};
};
index.html:
<!doctype html>
<html ng-app="plunker">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.6.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="ModalDemoCtrl">
<button class="btn" ng-click="open()">Open me!</button>
<div ng-show="selected">Selection from a modal: {{ selected }}</div>
</div>
</body>
</html>
modal.html:
<div class="modal-header">
<h3>I''m a modal!</h3>
</div>
<textarea ng-model="text"></textarea>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
¿Por qué no puedo obtener $ scope.text definido en ModalInstanceCtrl, aunque puedo usar $ scope.ok y $ scope.cancel?
Parece un problema de alcance. Lo tengo para que funcione así:
var ModalInstanceCtrl = function ($scope, $modalInstance) {
$scope.input = {};
$scope.ok = function () {
alert($scope.input.abc);
};
$scope.cancel = function () {
$modalInstance.dismiss(''cancel'');
};
};
HTML:
<textarea ng-model="input.abc"></textarea>
Vamos a tratar de explicar el motivo. código fuente modal ui-bootstrap:
.directive(''modalWindow'', [''$modalStack'', ''$timeout'', function ($modalStack, $timeout) {
return {
restrict: ''EA'',
scope: {
index: ''@'',
animate: ''=''
},
replace: true,
transclude: true,
templateUrl: function(tElement, tAttrs) {
return tAttrs.templateUrl || ''template/modal/window.html'';
},
y la plantilla sourcecode - window.html:
<div tabindex="-1" role="dialog" class="modal fade" ng-class="{in: animate}" ng-style="{''z-index'': 1050 + index*10, display: ''block''}" ng-click="close($event)">
<div class="modal-dialog" ng-class="{''modal-sm'': size == ''sm'', ''modal-lg'': size == ''lg''}"><div class="modal-content" modal-transclude></div></div>
hay una directiva modal-transclude , su contenido de diálogo se insertará en él, es código fuente:
.directive(''modalTransclude'', function () {
return {
link: function($scope, $element, $attrs, controller, $transclude) {
$transclude($scope.$parent, function(clone) {
$element.empty();
$element.append(clone);
});
}
};
})
ahora eche un vistazo al documento oficial de $ compile:
Transclusion Functions
When a directive requests transclusion, the compiler extracts its contents and provides
a transclusion function to the directive''s link function and controller.
This transclusion function is a special linking function that will return the compiled
contents linked to a **new transclusion scope.**
transclude creará un nuevo ámbito de alcance del controlador
Actualización de noviembre de 2014: el problema se soluciona con angular-ui-bootstrap 0.12.0 : el alcance de la transclusión se fusiona con el alcance del controlador. No hay necesidad de hacer nada. Solo quédate con:
<textarea ng-model="text"></textarea>
Antes de 0.12.0:
Los modales de UI angular están usando la transclusión para adjuntar contenido modal, lo que significa que cualquier nueva entrada de ámbito dentro de modal se crea en el alcance del niño.
Debe usar la herencia e inicializar la entrada de text
vacía en el $scope
o puede adjuntar explícitamente la entrada al alcance principal:
<textarea ng-model="$parent.text"></textarea>