Reputation: 5253
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>
Why I can't get the $scope.text defined in ModalInstanceCtrl, even though I can use $scope.ok and $scope.cancel?
Upvotes: 53
Views: 51659
Reputation: 17145
Update Nov 2014: the issue is fixed with angular-ui-bootstrap 0.12.0 - the transclusion scope is merged with the controller's scope. There is no need to do anything. Just stay with:
<textarea ng-model="text"></textarea>
Before 0.12.0:
Angular-UI modals are using transclusion to attach modal content, which means any new scope entries made within modal are created in child scope.
You should use inheritance and initialize empty text
entry in parent $scope
or you can explicitly attach the input to parent scope:
<textarea ng-model="$parent.text"></textarea>
Upvotes: 16
Reputation: 131
Let'me try to explain the reason. ui-bootstrap modal sourcecode:
.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';
},
and the template 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>
there is a directive modal-transclude,your dialog content will insert into it, it's sourcecode:
.directive('modalTransclude', function () {
return {
link: function($scope, $element, $attrs, controller, $transclude) {
$transclude($scope.$parent, function(clone) {
$element.empty();
$element.append(clone);
});
}
};
})
now take a look at offical doc of $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 will create a new scope of controller scope
Upvotes: 3
Reputation: 43947
Looks like a scope issue. I got it to work like this:
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>
Upvotes: 72