I want to set up a httpInterceptor to show a common modal dialog when a http request fails. I'm using https://angular-ui.github.io/bootstrap/ for the modal dialog.
I tried
app.config(function ($httpProvider, $uibModal) { ...
but got the error [$injector:modulerr] Failed to instantiate module app due to: Error: [$injector:unpr] Unknown provider: $uibModal
This answer indicates it's only possible to pass providers when configuring, so I then tried
app.config(function ($httpProvider, $uibModalProvider) {
which works up the point where I want to open the modal
var modalInstance = $uibModalProvider.open(
and I get the error that the object doesn't support the proprty or method open. How do I get from the provider to a modal instance or is there another way of achieving this?
Look at following sample:
(function(angular) {
'use strict';
var module = angular.module('app', ['ngAnimate', 'ui.bootstrap']);
module.controller('appController', ['$http', '$log', function($http, $log) {
var vm = this;
vm.sendRequest = sendRequest;
function sendRequest(){
$log.info('Try sending a request');
$http.get('/fake/');
}
}]);
module.controller('ModalInstanceCtrl', ['$scope', '$uibModalInstance', function ($scope, $uibModalInstance) {
$scope.ok = function () {
$uibModalInstance.dismiss('cancel');
};
}]);
module.factory('myHttpInterceptor', ['$log', '$injector', function($log, $injector) {
var interceptor = {
'responseError': function(config) {
$log.info('Request error');
// injecting $uibModal directly cause Circular Dependency error
// following method is a fix of it
$injector.get('$uibModal').open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: 'sm'
});
return config;
}
};
return interceptor;
}]);
module.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('myHttpInterceptor');
}]);
})(window.angular);
body { padding: 20px; }
<!doctype html>
<html lang="en">
<head>
<title>Interceptor & $uibModal sample</title>
<meta charset="UTF-8">
<!-- AngularJS -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.2.4.js"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" >
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css" >
</head>
<body ng-app="app">
<div class="panel panel-default" ng-controller="appController as vm">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Error!</h3>
</div>
<div class="modal-body">
Hello
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="ok()">OK</button>
</div>
</script>
<div class="panel-heading">
Send failing request
</div>
<div class="panel-body">
<button type="button" class="btn btn-primary" ng-click="vm.sendRequest()">Send request</button>
</div>
</div>
</body>
</html>
Use the $injector
service to get an instance of $uibModal
.
app.config(function($httpProvider) {
//To configure an interceptor you have to push a function
//or name of a registered service into the array. The function
//or service is where you call $injector.get();
$httpProvider.interceptors.push(function($injector) {
return {
responseError: function(res) {
var templateUrl = 'http://badurl'; //This can cause infinite recursion!
if (res.config.url === templateUrl) return null; //One way to prevent infinite recursion.
var $uibModal = $injector.get('$uibModal');
var modalInstance = $uibModal.open({
templateUrl: templateUrl
});
return res;
}
}
})
});
But beware of causing an infinite recursion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With