私が見た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
_
あなたが抱えている問題は、注入に利用できない値を注入しようとしていることです。インジェクターに登録されている値のみを注入できます。
コードのロジックにも欠陥があります。メインコントローラーでモーダルを作成していますが、ディレクティブでモーダルを閉じようとしています。理想的には、モーダルは(リンク関数を介して)ディレクティブによってトリガーされ、そこからok/cancelすることができます。
私の http://plnkr.co/edit/3p1rXAymd7BilyklgxKy?p=preview を参照してください。考えられるアプローチの1つとして、メインコントローラーのモーダルを閉じてキャンセルするコードを保持しています。
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());
});
};
});
問題は、$modalInstance
は$modal.open
に提供したコントローラーにのみ注入できることです。ソースをチェックしてください ここ :
$modal.open = function (modalOptions) {
...
var modalInstance = {
...
};
...
if (modalOptions.controller) {
...
ctrlLocals.$modalInstance = modalInstance;
...
ctrlInstance = $controller(modalOptions.controller, ctrlLocals);
...
}
...
}
基本的に、コントローラーへの依存関係として$modalInstance
を追加しようとすると、AngularJSは$modalInstanceProvider
という名前の登録済みグローバルプロバイダーを探します。ここで問題となるのは、上記のコードを理解している場合、$modalInstance
はnotグローバルに登録されたプロバイダーではないということです。 $modal.open
に渡すコントローラーの依存関係としてのみ「存在」します。
残りのコードを読むと、$modal.open
が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
}
}
モーダルを簡単に作成するためのディレクティブを作成します。モーダルコンテンツは、テンプレートビューに基づいています。
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";
});
モーダルコントローラー(HelloCtrl)はビューコントローラー(Hello2)の後にレンダリングされるため、モーダル出力が「HelloWorldsszzXico」になることに注意してください。
返信はさらに遅くなりますが、誰かが役に立つと思うかもしれません。
私はFernandoFelixの回答を強化し、コントローラーと通信する独自の非常に柔軟なディレクティブを作成しました。これは、この質問の解決策になると思います。
指令
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>
ポップアップタイプごとに1つのコントローラーとテンプレートであるため、次の方法で複数回呼び出すことができます。
<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>
モーダルサイズなど
モーダルリンク/ボタンのパラメータsize = "sm | lg"を追加するだけです。ここをクリックしてモーダルを開きます。標準サイズの場合は、パラメーターをスキップします。リンク関数attrsを使用して、自分で拡張することができます。
私は神田ですレイトリプレイ最も簡単な方法は使用することです
$scope.$parent.$close(result);
$scope.$parent.$dismiss(reason);
これは、ディレクティブコントローラーから機能します。