Javascript angular-ui bootstrap $modal 服务使用指令代替
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28588318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
angular-ui bootstrap $modal service using directive instead
提问by core
The examples I see of using angular-ui/bootstrap's $modalalways look something like this:
我看到的使用 angular-ui/bootstrap 的例子$modal总是像这样:
$modal.open({
templateUrl: 'modaltemplate.html',
controller: function($scope) {
...
}
});
What if I want to use a directive, instead? Like this:
如果我想使用指令怎么办?像这样:
$modal.open({
template: '<my-modal-directive></my-modal-directive>'
// no "controller" property; use directive's controller
});
The markup for my-modal-directiverenders fine, and I've moved the controllerproperty into the my-modal-directivedefinition object, but now getting this error from the my-modal-directive:
my-modal-directive呈现的标记很好,我已将该controller属性移到my-modal-directive定义对象中,但现在从以下位置收到此错误my-modal-directive:
Error: [$injector:unpr] Unknown provider: $modalInstanceProvider <- $modalInstance
Can anyone point me to an example where $modaluses a directive where that directive defines the controller?
任何人都可以指出我$modal使用指令的示例,该指令定义了controller?
For example, this works, where I've replaced the templateUrlwith a directive:
例如,这有效,我templateUrl用指令替换了:
http://plnkr.co/edit/YrGaF83GH6bzZPRR55GK?p=preview
But when I move the controller from $modal.open()into the directive, that's when the error happens:
但是当我将控制器从$modal.open()指令中移动时,就会发生错误:
http://plnkr.co/edit/aLBT239EpL004DRh4jll?p=preview
采纳答案by thedoctor
The issue you have is that you are trying to inject values which are not available for injection. Only values registered with the injector can be injected.
您遇到的问题是您正在尝试注入无法注入的值。只能注入注入器注册的值。
The logic of you code is also flawed, you are creating the modal in your main controller but trying to close it in the directive. Ideally, the modal should be triggered by the directive (via it's link function), and then you can ok/cancel it from there.
您的代码逻辑也有缺陷,您正在主控制器中创建模态,但试图在指令中关闭它。理想情况下,模态应该由指令触发(通过它的链接功能),然后您可以从那里确定/取消它。
See my http://plnkr.co/edit/3p1rXAymd7BilyklgxKy?p=previewfor one possible approach, I have kept the code that closes and cancels the modal in the main controller.
有关一种可能的方法,请参阅我的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());
});
};
});
回答by Sergiu Paraschiv
The problem is that $modalInstancecan only be injected in the controller that you provide to $modal.open.
Check out the sources here:
问题是$modalInstance只能注入到您提供给的控制器中$modal.open。在此处查看来源:
$modal.open = function (modalOptions) {
...
var modalInstance = {
...
};
...
if (modalOptions.controller) {
...
ctrlLocals.$modalInstance = modalInstance;
...
ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
...
}
...
}
In essence when you try to add $modalInstanceas a dependency to your controller AngularJS looks for a registered global provider named $modalInstanceProvider. Now the trouble is, if you understood the code above, that $modalInstanceis nota globally registered provider. It only "exists" as a dependency for the controller you pass to $modal.open.
本质上,当您尝试将$modalInstance依赖项添加到控制器时,AngularJS 会查找名为$modalInstanceProvider. 现在的问题是,如果你理解上面的代码,这$modalInstance是不是一个全球的注册供应商。它仅作为您传递给的控制器的依赖项“存在” $modal.open。
If you read the rest of the code you'll notice that $modal.openreturns modalInstance, maybe you can use that.
如果您阅读其余的代码,您会注意到$modal.openreturn modalInstance,也许您可以使用它。
Something like 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
}
}
回答by Fernando Felix
I create a directive to create modals easily. A modal content is based on a template view.
我创建了一个指令来轻松创建模态。模态内容基于模板视图。
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,
});
});
}
};
});
Example how to use it:
示例如何使用它:
index.html
索引.html
<a modal-view-url="hello.html" modal-controller="HelloCtrl" href="#">
Click here to open the modal
</a>
hello.html
你好.html
<h1> Hello World {{name}} </h1>
HelloCtrl.js
你好Ctrl.js
angular.module('yourApp').controller('HelloCtrl',
function ($scope, $modalInstance) {
// $modalInstance: same from from ui bootstrap
$scope.name = "Xico";
});
A modal view can have its own controller. Example:
模态视图可以有自己的控制器。例子:
hello.html (modified)
hello.html (修改)
<h1 ng-controller="Hello2Ctrl"> {{msg}} {{name}} </h1>
Hello2Ctrl.js
Hello2Ctrl.js
angular.module('yourApp').controller('Hello2Ctrl',
function ($scope) {
$scope.msg = "Hello Worldsszz";
$scope.name = "Zefa";
});
Observe that the modal output will be "Hello Worldsszz Xico", because the modal controller (HelloCtrl) will be rendered after view controller (Hello2).
观察到模态输出将是“Hello Worldsszz Xico”,因为模态控制器(HelloCtrl)将在视图控制器(Hello2)之后呈现。
回答by Karol Websky
It's even more late reply, but someone may find it useful.
回复更晚,但有人可能会发现它很有用。
I have enhanced Fernando Felix answer and made my own quite flexible directive which communicates with the controller, which I think might be solution for this question.
我已经增强了 Fernando Felix 的答案,并制定了我自己的非常灵活的指令来与控制器进行通信,我认为这可能是这个问题的解决方案。
Directive
指示
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);
Controller
控制器
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);
inline template
内联模板
<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>
It's one controller and template per popup type, then you can call it multiple times with:
它是每个弹出类型的一个控制器和模板,然后您可以多次调用它:
<a modal-url="hello.html" modal-controller="HelloCtrl" value="yourVal" ng-init="yourVal='test'" href="#">Click here to open the modal</a>
You can initialize value with whatever - ie. object, array etc.
你可以用任何东西初始化值 - 即。对象、数组等
or external template
或外部模板
Pretty much the same, just url changes and template file is used for template.
几乎相同,只是 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
测试1.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>
Modal size etc.
模态大小等
Just add parameter size="sm|lg" for the modal link/button ie. Click here to open the modal For standard size skip the parameter. You may enhance it yourself using link function attrs.
只需为模态链接/按钮添加参数 size="sm|lg" 即。单击此处打开模态 对于标准尺寸跳过该参数。您可以使用链接函数 attrs 自己增强它。
回答by Dimpu Aravind Buddha
I'm kanda late replay put simplest way is to use
I'm kanda late replay put 最简单的方法是使用
$scope.$parent.$close(result);
$scope.$parent.$dismiss(reason);
This works form your directive controller.
这适用于您的指令控制器。

