angular-ui bootstrap $modal 服务使用指令代替
angular-ui bootstrap $modal service using directive instead
我看到的使用 angular-ui/bootstrap 的 $modal
的示例总是看起来像这样:
$modal.open({
templateUrl: 'modaltemplate.html',
controller: function($scope) {
...
}
});
如果我想改用指令怎么办?像这样:
$modal.open({
template: '<my-modal-directive></my-modal-directive>'
// no "controller" property; use directive's controller
});
my-modal-directive
的标记呈现良好,我已将 controller
属性 移动到 my-modal-directive
定义对象中,但现在从 my-modal-directive
:
Error: [$injector:unpr] Unknown provider: $modalInstanceProvider <- $modalInstance
谁能给我指出一个示例,其中 $modal
使用一个指令,该指令定义了 controller
?
例如,这有效,我用指令替换了 templateUrl
:
http://plnkr.co/edit/YrGaF83GH6bzZPRR55GK?p=preview
但是当我将控制器从 $modal.open()
移动到指令中时,错误发生了:
http://plnkr.co/edit/aLBT239EpL004DRh4jll?p=preview
问题是 $modalInstance
只能注入到您提供给 $modal.open
的控制器中。
查看来源 here:
$modal.open = function (modalOptions) {
...
var modalInstance = {
...
};
...
if (modalOptions.controller) {
...
ctrlLocals.$modalInstance = modalInstance;
...
ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
...
}
...
}
本质上,当您尝试将 $modalInstance
添加为控制器的依赖项时,AngularJS 会查找名为 $modalInstanceProvider
的已注册全局提供程序。现在的问题是,如果您理解上面的代码,那么 $modalInstance
是 而不是 全球注册的提供商。它仅 "exists" 作为传递给 $modal.open
.
的控制器的依赖项
如果您阅读其余代码,您会注意到 $modal.open
returns modalInstance
,也许您可以使用它。
类似于this:
function SomeController($modal) {
$scope.modal = {
instance: null
};
$scope.modal.instance = $modal.open({
template: '<my-modal-directive modal="modal"></my-modal-directive>',
scope: $scope
});
}
function MyModalDirective() {
scope: {
modal: '='
},
link: function($scope) {
// here you can access $scope.modal.instance
}
}
您遇到的问题是您正在尝试注入不可用于注入的值。只能注入注入器注册的值。
你的代码逻辑也有缺陷,你在主控制器中创建模态,但试图在指令中关闭它。理想情况下,模式应该由指令触发(通过它的 link 函数),然后你可以从那里 ok/cancel 它。
查看我的 http://plnkr.co/edit/3p1rXAymd7BilyklgxKy?p=preview 了解一种可能的方法,我在主控制器中保留了关闭和取消模态的代码。
angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').directive('myModal', function() {
return {
restrict: 'E',
templateUrl: 'myModalContent.html',
controller: function ($scope) {
$scope.selected = {
item: $scope.items[0]
};
}
};
});
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $modal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.open = function (size) {
var modalInstance;
var modalScope = $scope.$new();
modalScope.ok = function () {
modalInstance.close(modalScope.selected);
};
modalScope.cancel = function () {
modalInstance.dismiss('cancel');
};
modalInstance = $modal.open({
template: '<my-modal></my-modal>',
size: size,
scope: modalScope
}
);
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
});
我创建了一个指令来轻松创建模态。模态内容基于模板视图。
angular.module('your_app').directive('modalViewUrl', function ($modal) {
return {
restrict: 'A', // A: attribute
scope: { // isolate scope
'modalViewUrl': '@', // modal view url to render the modal content
'modalController': '@' // modal view controller (optional)
},
link: function($scope, element, attrs){
element.bind('click', function(){
var template =
'<div class="modal-body">' +
'<button ng-click="$close()" type="button" class="close" aria-label="Close">' +
'<span aria-hidden="true">×</span>' +
'</button>' +
'<div ng-include="\'' + $scope.modalViewUrl + '\'"></div>' +
'</div>';
// see modal reference from ui bootstrap at <http://angular-ui.github.io>
var modalInstance = $modal.open({
animation: true,
template: template,
controller: $scope.modalController,
});
});
}
};
});
使用示例:
index.html
<a modal-view-url="hello.html" modal-controller="HelloCtrl" href="#">
Click here to open the modal
</a>
hello.html
<h1> Hello World {{name}} </h1>
HelloCtrl.js
angular.module('yourApp').controller('HelloCtrl',
function ($scope, $modalInstance) {
// $modalInstance: same from from ui bootstrap
$scope.name = "Xico";
});
模态视图可以有自己的控制器。示例:
hello.html(修改)
<h1 ng-controller="Hello2Ctrl"> {{msg}} {{name}} </h1>
Hello2Ctrl.js
angular.module('yourApp').controller('Hello2Ctrl',
function ($scope) {
$scope.msg = "Hello Worldsszz";
$scope.name = "Zefa";
});
观察模态输出将是 "Hello Worldsszz Xico",因为模态控制器 (HelloCtrl) 将在视图控制器 (Hello2) 之后呈现。
我回复有点晚,最简单的方法是使用
$scope.$parent.$close(result);
$scope.$parent.$dismiss(reason);
这适用于您的指令控制器。
更晚的回复,但有人可能会觉得它有用。
我增强了 Fernando Felix 的回答,并制作了我自己的与控制器通信的非常灵活的指令,我认为这可能是这个问题的解决方案。
指令
var modalUrl = function ($modal) {
return {
restrict: 'A', // A: attribute
scope: { // isolate scope
'modalUrl': '@', // modal view url to render the modal content
'modalController': '@', // modal view controller (optional)
'value': "="
},
link: function(scope, element, attrs){
console.log('modalUrl link');
var modalInstance;
var template = [
'<div class="modal-body">',
'<button ng-click="$close()" type="button" class="close" aria-label="Close">',
'<span aria-hidden="true">×</span>',
'</button>',
'<div ng-include="\'' + scope.modalUrl + '\'"></div>',
'</div>'
].join('');
element.bind('click', function(){
// see modal reference from ui bootstrap at <http://angular-ui.github.io>
modalInstance = $modal.open({
size: attrs.size,
animation: true,
template: template,
resolve: {
params: function () {
console.log('value passed to modal:');
console.log(scope.value);
return scope.value;
}
},
controller: scope.modalController
});
modalInstance.result.then(
function (returnValue) {
// alert('value: '+returnValue);
console.log('modal returnValue:');
console.log(returnValue);
scope.value = returnValue;
}, function () {
console.log('Modal dismissed at: ' + new Date());
}
);
});
}
};
}
modalUrl.$inject = ['$modal'];
angular.module('app').directive('modalUrl', modalUrl);
控制器
var HelloCtrl = function ($scope, $modalInstance, modalVal) {
// $modalInstance: same from from ui bootstrap
console.log('Hello init!');
// modalVal is the init modal value passed via directive
console.log(modalVal);
// your code
$scope.name = modalVal;
$scope.ok = function() {
$modalInstance.close(this.name); // returnValue
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
HelloCtrl.$inject = ['$scope', '$modalInstance','params'];
angular.module('app').controller('HelloCtrl',HelloCtrl);
内联模板
<script type="text/ng-template" id="hello.html">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<input type="text" ng-model="name" />
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn" ng-click="cancel()">Cancel</button>
</div>
</script>
每个弹出窗口类型一个控制器和一个模板,然后您可以多次调用它:
<a modal-url="hello.html" modal-controller="HelloCtrl" value="yourVal" ng-init="yourVal='test'" href="#">Click here to open the modal</a>
您可以使用任何方式初始化值 - 即。对象、数组等
或外部模板
几乎相同,只是 url 变化和模板文件用于模板。
<a modal-url="/modal/test1.html" modal-controller="HelloCtrl" value="yourVal" ng-init="yourVal='test'" href="#">Click here to open the modal</a>
test1.html
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<input type="text" ng-model="name" />
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn" ng-click="cancel()">Cancel</button>
</div>
模态大小等
只需为模态 link/button 添加参数 size="sm|lg" 即。
单击此处打开模态
对于标准尺寸,请跳过该参数。
您可以使用 link 函数 attrs.
自行增强它
我看到的使用 angular-ui/bootstrap 的 $modal
的示例总是看起来像这样:
$modal.open({
templateUrl: 'modaltemplate.html',
controller: function($scope) {
...
}
});
如果我想改用指令怎么办?像这样:
$modal.open({
template: '<my-modal-directive></my-modal-directive>'
// no "controller" property; use directive's controller
});
my-modal-directive
的标记呈现良好,我已将 controller
属性 移动到 my-modal-directive
定义对象中,但现在从 my-modal-directive
:
Error: [$injector:unpr] Unknown provider: $modalInstanceProvider <- $modalInstance
谁能给我指出一个示例,其中 $modal
使用一个指令,该指令定义了 controller
?
例如,这有效,我用指令替换了 templateUrl
:
http://plnkr.co/edit/YrGaF83GH6bzZPRR55GK?p=preview
但是当我将控制器从 $modal.open()
移动到指令中时,错误发生了:
http://plnkr.co/edit/aLBT239EpL004DRh4jll?p=preview
问题是 $modalInstance
只能注入到您提供给 $modal.open
的控制器中。
查看来源 here:
$modal.open = function (modalOptions) {
...
var modalInstance = {
...
};
...
if (modalOptions.controller) {
...
ctrlLocals.$modalInstance = modalInstance;
...
ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
...
}
...
}
本质上,当您尝试将 $modalInstance
添加为控制器的依赖项时,AngularJS 会查找名为 $modalInstanceProvider
的已注册全局提供程序。现在的问题是,如果您理解上面的代码,那么 $modalInstance
是 而不是 全球注册的提供商。它仅 "exists" 作为传递给 $modal.open
.
如果您阅读其余代码,您会注意到 $modal.open
returns modalInstance
,也许您可以使用它。
类似于this:
function SomeController($modal) {
$scope.modal = {
instance: null
};
$scope.modal.instance = $modal.open({
template: '<my-modal-directive modal="modal"></my-modal-directive>',
scope: $scope
});
}
function MyModalDirective() {
scope: {
modal: '='
},
link: function($scope) {
// here you can access $scope.modal.instance
}
}
您遇到的问题是您正在尝试注入不可用于注入的值。只能注入注入器注册的值。
你的代码逻辑也有缺陷,你在主控制器中创建模态,但试图在指令中关闭它。理想情况下,模式应该由指令触发(通过它的 link 函数),然后你可以从那里 ok/cancel 它。
查看我的 http://plnkr.co/edit/3p1rXAymd7BilyklgxKy?p=preview 了解一种可能的方法,我在主控制器中保留了关闭和取消模态的代码。
angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').directive('myModal', function() {
return {
restrict: 'E',
templateUrl: 'myModalContent.html',
controller: function ($scope) {
$scope.selected = {
item: $scope.items[0]
};
}
};
});
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $modal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.open = function (size) {
var modalInstance;
var modalScope = $scope.$new();
modalScope.ok = function () {
modalInstance.close(modalScope.selected);
};
modalScope.cancel = function () {
modalInstance.dismiss('cancel');
};
modalInstance = $modal.open({
template: '<my-modal></my-modal>',
size: size,
scope: modalScope
}
);
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
});
我创建了一个指令来轻松创建模态。模态内容基于模板视图。
angular.module('your_app').directive('modalViewUrl', function ($modal) {
return {
restrict: 'A', // A: attribute
scope: { // isolate scope
'modalViewUrl': '@', // modal view url to render the modal content
'modalController': '@' // modal view controller (optional)
},
link: function($scope, element, attrs){
element.bind('click', function(){
var template =
'<div class="modal-body">' +
'<button ng-click="$close()" type="button" class="close" aria-label="Close">' +
'<span aria-hidden="true">×</span>' +
'</button>' +
'<div ng-include="\'' + $scope.modalViewUrl + '\'"></div>' +
'</div>';
// see modal reference from ui bootstrap at <http://angular-ui.github.io>
var modalInstance = $modal.open({
animation: true,
template: template,
controller: $scope.modalController,
});
});
}
};
});
使用示例:
index.html
<a modal-view-url="hello.html" modal-controller="HelloCtrl" href="#">
Click here to open the modal
</a>
hello.html
<h1> Hello World {{name}} </h1>
HelloCtrl.js
angular.module('yourApp').controller('HelloCtrl',
function ($scope, $modalInstance) {
// $modalInstance: same from from ui bootstrap
$scope.name = "Xico";
});
模态视图可以有自己的控制器。示例:
hello.html(修改)
<h1 ng-controller="Hello2Ctrl"> {{msg}} {{name}} </h1>
Hello2Ctrl.js
angular.module('yourApp').controller('Hello2Ctrl',
function ($scope) {
$scope.msg = "Hello Worldsszz";
$scope.name = "Zefa";
});
观察模态输出将是 "Hello Worldsszz Xico",因为模态控制器 (HelloCtrl) 将在视图控制器 (Hello2) 之后呈现。
我回复有点晚,最简单的方法是使用
$scope.$parent.$close(result);
$scope.$parent.$dismiss(reason);
这适用于您的指令控制器。
更晚的回复,但有人可能会觉得它有用。
我增强了 Fernando Felix 的回答,并制作了我自己的与控制器通信的非常灵活的指令,我认为这可能是这个问题的解决方案。
指令
var modalUrl = function ($modal) {
return {
restrict: 'A', // A: attribute
scope: { // isolate scope
'modalUrl': '@', // modal view url to render the modal content
'modalController': '@', // modal view controller (optional)
'value': "="
},
link: function(scope, element, attrs){
console.log('modalUrl link');
var modalInstance;
var template = [
'<div class="modal-body">',
'<button ng-click="$close()" type="button" class="close" aria-label="Close">',
'<span aria-hidden="true">×</span>',
'</button>',
'<div ng-include="\'' + scope.modalUrl + '\'"></div>',
'</div>'
].join('');
element.bind('click', function(){
// see modal reference from ui bootstrap at <http://angular-ui.github.io>
modalInstance = $modal.open({
size: attrs.size,
animation: true,
template: template,
resolve: {
params: function () {
console.log('value passed to modal:');
console.log(scope.value);
return scope.value;
}
},
controller: scope.modalController
});
modalInstance.result.then(
function (returnValue) {
// alert('value: '+returnValue);
console.log('modal returnValue:');
console.log(returnValue);
scope.value = returnValue;
}, function () {
console.log('Modal dismissed at: ' + new Date());
}
);
});
}
};
}
modalUrl.$inject = ['$modal'];
angular.module('app').directive('modalUrl', modalUrl);
控制器
var HelloCtrl = function ($scope, $modalInstance, modalVal) {
// $modalInstance: same from from ui bootstrap
console.log('Hello init!');
// modalVal is the init modal value passed via directive
console.log(modalVal);
// your code
$scope.name = modalVal;
$scope.ok = function() {
$modalInstance.close(this.name); // returnValue
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
}
HelloCtrl.$inject = ['$scope', '$modalInstance','params'];
angular.module('app').controller('HelloCtrl',HelloCtrl);
内联模板
<script type="text/ng-template" id="hello.html">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<input type="text" ng-model="name" />
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn" ng-click="cancel()">Cancel</button>
</div>
</script>
每个弹出窗口类型一个控制器和一个模板,然后您可以多次调用它:
<a modal-url="hello.html" modal-controller="HelloCtrl" value="yourVal" ng-init="yourVal='test'" href="#">Click here to open the modal</a>
您可以使用任何方式初始化值 - 即。对象、数组等
或外部模板
几乎相同,只是 url 变化和模板文件用于模板。
<a modal-url="/modal/test1.html" modal-controller="HelloCtrl" value="yourVal" ng-init="yourVal='test'" href="#">Click here to open the modal</a>
test1.html
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
<input type="text" ng-model="name" />
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn" ng-click="cancel()">Cancel</button>
</div>
模态大小等
只需为模态 link/button 添加参数 size="sm|lg" 即。 单击此处打开模态 对于标准尺寸,请跳过该参数。 您可以使用 link 函数 attrs.
自行增强它