Unknown provider: $confirmModalProvider <- $confirmModal <- confirmModalCtrl
Why am I getting this error? I'm trying to use AngularJS UI Bootstrap to open a modal and get the result. I get this error when I trigger $scope.deleteQuestion(). Any idea what I'd doing wrong here?
var crtPromoCtrl = angular.module('crtPromoCtrl', ['crtPromoSrv']);
crtPromoCtrl.controller('surveyCtrl', ['$scope', '$modal', 'surveySrv', function($scope, $modal, surveySrv)
{
$scope.questions = surveySrv.getQuestions();
$scope.editQuestion = function(index)
{
surveySrv.setEditQuestion(index);
};
$scope.deleteQuestion = function(index)
{
var confirmModal = $modal.open({
templateUrl: 'confirm-delete.html',
controller: 'confirmModalCtrl',
size: 'sm'
});
confirmModal.result.then(function(msg)
{
console.log(msg);
});
return false;
};
}]);
crtPromoCtrl.controller('confirmModalCtrl', ['$scope', '$confirmModal', function($scope, $confirmModal)
{
$scope.yes = function()
{
$confirmModal.close('yes');
};
$scope.no = function()
{
$confirmModal.dismiss('no');
};
}]);
EDIT: https://angular-ui.github.io/bootstrap/#/modal
You second controller should use $modalInstance instead of $confirmModal
Please note that $modalInstance represents a modal window (instance)
dependency.
Code
crtPromoCtrl.controller('confirmModalCtrl', ['$scope', '$modalInstance', function($scope, $modalInstance) {
$scope.yes = function() {
$modalInstance.close('yes');
};
$scope.no = function() {
$modalInstance.dismiss('no');
};
}]);
Related
I have two controllers. I want to update a variable from one controller to another controller using service but its not updating.
I want the variable $scope.names in controller 'select' to update in the controller 'current' and display it
app.controller('select', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$http.get('/myapp/stocknames').
success(function(data) {
$scope.names=data;
myService.names=data;
});
}]);
I am using myService to exchange the data between the two controllers. I have declared in my service.
app.service('myService', function($http, $rootScope) {
this.names=[]
});
app.controller('current', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$scope.names=myService.names;
console.log($scope.names);
}]);
Can you please help. How should I make the current controller update the data once the $scope.names variable in the select controller is updated?
According to me what I am doing should work :-/
There are many way to archive this:
First:
By watching for the service variable data change
var app = angular.module('plunker', []);
app.service('dataService', function() {
this.serviceData = "test";
});
app.controller('MainCtrl', function($scope, dataService) {
$scope.mainClickHandler = function(mainData) {
dataService.serviceData = mainData;
}
});
app.controller('SubCtrl', function($scope, dataService) {
$scope.name = 'World';
$scope.getServiceData = function() {
return dataService.serviceData;
}
$scope.$watch("getServiceData()", function(newValue, oldValue) {
if (oldValue != newValue) {
$scope.name = newValue;
}
});
});
http://plnkr.co/edit/G1C81qvDD179NILMMxWb
Second:
Using event broadcast
var app = angular.module('plunker', []);
app.factory('dataService', function($rootScope) {
var serviceData = {
"mydata": "test"
};
$rootScope.$watch(function() {
return serviceData.mydata;
}, function(newValue, oldValue, scope) {
$rootScope.$broadcast('dataService:keyChanged', newValue);
}, true);
return serviceData;
});
app.controller('MainCtrl', function($scope, dataService) {
$scope.mainClickHandler = function(mainData) {
dataService.mydata = mainData;
}
});
app.controller('SubCtrl', function($scope, $rootScope, dataService) {
$scope.name = 'World';
$rootScope.$on('dataService:keyChanged', function currentCityChanged(event, value) {
console.log('data changed', event, value);
$scope.name = value;
});
});
http://plnkr.co/edit/tLsejetcySSyWMukr89u?p=preview
Third:
Using callback
var app = angular.module('plunker', []);
app.service('dataService', function() {
var serviceData = "test";
var callback = null;
this.updateServiceData = function(newData){
serviceData = newData;
if(null!==callback)
{
callback();
}
};
this.getServiceData = function(){
return serviceData;
};
this.regCallback = function(dataCallback){
callback = dataCallback;
};
});
app.controller('MainCtrl', function($scope, dataService) {
$scope.mainClickHandler = function(mainData) {
dataService.updateServiceData(mainData);
}
});
app.controller('SubCtrl', function($scope, dataService) {
$scope.name = 'World';
$scope.dataChangeCalback = function() {
$scope.name = dataService.getServiceData();
}
dataService.regCallback($scope.dataChangeCalback);
});
http://plnkr.co/edit/vrJM1hqD8KwDCf4NkzJX?p=preview
One way to do this is we can bind the entire service to the scope:
myApp.controller('select', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$scope.myService = myService;
$scope.click = function () {
myService.names = "john";
};
And then we change the myService.names directly
current controller should look like this:
myApp.controller('current', ['$scope', '$http', 'myService', function($scope,$http, myService) {
$scope.names=myService.names;
console.log($scope.names);
$scope.$watch(function() { return myService.names; }, function(newVal, oldVal) {
$scope.names = newVal;
});
}]);
}]);
We then use a watcher expression.
or a watcherExpression See for more details.
I am extends bootstrap modal like this:
.directive("modal", [function(){
var controller = function($scope, $attrs, $element, $uibModal){
var defaultOptions = {
title: "Modal title",
content: "Modal body",
controller: "DefaultModalController",
templateUrl: "js/dev/shared/directives/templates/default-modal-template.html"
};
$element.on($scope.event, function(){
var userOptions = {
title: $attrs.title,
content: $attrs.content,
templateUrl: $attrs.templateUrl,
controller: $attrs.controller
};
options = angular.extend({},defaultOptions, userOptions || {});
$uibModal.open({
templateUrl: options.templateUrl,
controller: options.controller,
resolve: {
options: function () {
return options
}
}
});
});
};
return {
restrict: "A",
scope: {
event: "#"
},
controller: ["$scope", "$attrs", "$element", "$uibModal", controller]
}
}])
.controller("DefaultModalController", ["$scope", "$modalInstance", "options",
function($scope, $modalInstance, options){
$scope.modalOptions = options;
$scope.close = function(){
$modalInstance.close();
}
}]);
and my test looks like this:
descr
ibe("ModalDirective", ()=>{
var element,
compile,
scope,
controller;
beforeEach(module("app.directive"));
beforeEach(inject((_$compile_, _$rootScope_, _$controller_)=>{
compile = _$compile_;
controller = _$controller_;
scope = _$rootScope_.$new();
element = angular.element("<button modal>test</button>")
}));
it("should create default modal window", ()=>{
element = compile(element)(scope);
console.error(element.html());
expect(true).toBeTruthy();
})
});
but when compile(element)(scope) is executing I've got this error:
TypeError: 'undefined' is not an object (evaluating 'd.indexOf')
at a (https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.7/angular.min.js:179)
What should I do to fix it?
[ EDIT ]
I fixed this, the problem was in creating directive.
In directive definition I have:
scope: {
event: "#"
}
and my template was <button modal>test</button> when I changed it to <button modal event='click'>test</button> problem was solved.
I already have seem other topics with this kind of issue, but no one could help me... So here is my issue:
I have a navbar with a button for search, this buttons makes and get request from a webservice and returns a json object which must be apply to fill an table list. The problem is, my button and my table are in separated controllers, and it does work like I expected.
var app = angular.module('clientRest', []).controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.getContatos();
}]).controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
}]).service('loadLista', function() {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
}
};
});
My code...
When I call listar() from pesquisa controller I need to send received data to $scope.contatos from lista controller to make my ng-repeat work, everything with a single click.
How can I do it?
Thanks everyone
Better to use a service to share data between two controllers / modules as this might be the best approach. You can refer the code segment given below to understand the concept.
angular.module('app.A', [])
.service('ServiceA', function() {
this.getValue = function() {
return this.myValue;
};
this.setValue = function(newValue) {
this.myValue = newValue;
}
});
angular.module('app.B', ['app.A'])
.service('ServiceB', function(ServiceA) {
this.getValue = function() {
return ServiceA.getValue();
};
this.setValue = function() {
ServiceA.setValue('New value');
}
});
In order to trigger the data receipt event, you may use
Broadcast / emit messages - with #broadcast / #emit
An angular promise with a call back
Controller initiation function to reload the previously read information from a service
.controller('MyController', function($scope, ServiceA) {
$scope.init = function() {
$scope.myValue = ServiceA.getValue();
};
// Call the function to initialize during Controller instantiation
$scope.init();
});
Use $rootScope.$emit to emit a change event when setting the variable and use $on to get the value in the lista controller. I used customListAr here just to demostrate a button click. Does this help?
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', '$rootScope',
function($scope, loadLista, $rootScope) {
console.log(loadLista);
$scope.contatos = loadLista.getContatos();
$rootScope.$on('change', function() {
$scope.contatos = loadLista.getContatos();
});
}
])
.controller('pesquisa', ['$scope', '$http', 'loadLista',
function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
$scope.customListAr = function() {
loadLista.setContatos(["item 1" , "item 2", "item 3"]);
}
}
])
.service('loadLista', ['$rootScope',
function($rootScope) {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
$rootScope.$emit('change');
}
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="clientRest">
<div ng-controller="lista">
<ul>
<li ng-repeat="a in contatos">{{a}}</li>
</ul>
</div>
<div ng-controller="pesquisa">
<button ng-click="customListAr()">Click Me</button>
</div>
</div>
Your problem is that when you do $scope.contatos = loadLista.getContatos(); you are setting a static value, and angular is unable to effectively create a watcher for that object because your setContatos method is creating a new object each time. To get around this, have the controller's scope hold a reference to the parent object and then it will automatically have a watcher on that object.
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.contatos;
}])
.controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato"
).success(function (response) {
loadLista.contatos.data = response;
});
};
}])
.service('loadLista', function() {
var lista = {
contatos: {},
};
return lista;
});
// view:
<ul>
<li ng-repeat="contato in contatos.data">
{{ contato }}
</li>
</ul>
I've tried this plunker
http://plnkr.co/edit/s902hdUIjKJo0h6u6k0l?p=preview
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $modalInstance, items) {
but it gives an error
Error: [$injector:unpr] Unknown provider: itemsProvider <- items
I want to have two buttons with 2 differents modal
There are lot of syntax mistakes:
Updated plunker http://plnkr.co/edit/vgM5PLyVgluOeikGvVSA?p=preview
Changes made in JS:-
angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $modal, $log) {
$scope.items = ['item1', 'item2', 'item3'];
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
});
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl2', function ($scope, $modal, $log) {
$scope.items2 = ['item12', 'item22', 'item32'];
$scope.open = function (size) {
var modalInstance2 = $modal.open({
templateUrl: 'myModalContent2.html',
controller: 'ModalInstanceCtrl2',
size: size,
resolve: {
items2: function () {
return $scope.items2;
}
}
});
modalInstance2.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
});
// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $modalInstance, items) {
$scope.items = items;
$scope.selected = {
item: $scope.items[0]
};
$scope.ok = function () {
$modalInstance.close($scope.selected.item);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl2', function ($scope, $modalInstance, items2) {
$scope.items2 = items2;
$scope.selected = {
item: $scope.items2[0]
};
$scope.ok = function () {
$modalInstance.close($scope.selected.item2);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
You can try my Angular Dialog Service, its built on top of ui.bootstrap's modal but offers prefabricated modals for errors, notifications, progression, confirmations and custom dialogs. It allows you to set configuration as well in your application's config function using 'dialogsProvider' so you don't have to setup keyboard and backdrop settings everytime. There's also support for using angular-translate and fontAwesome.
You can find it here: https://github.com/m-e-conroy/angular-dialog-service
or on bower.io.
I have create my own LoggerService but if I use it I get error:
FOrder.query is not a function
If i remove all LoggerService calls in controller all work fine, why i can't use LoggerService?
services.js
angular.module('GSAdmin.services', ['ngResource'])
.factory('FOrder', ['$resource', function($resource) {
return $resource('/api/order/:orderId');
}])
.service('LoggerService', [function(){
var _logList = [];
this.getLast = function(){
return _logList[_logList.length-1];
};
this.getLog = function(){
return _logList;
};
this.log = function(text) {
_logList.push(text);
};
}])
controller.js
.controller('OrderController', ['$scope', 'FOrder', 'LoggerService',
function($scope, FOrder, LoggerService) {
FOrder.query(function(data){
$scope.orders = data;
});
$scope.log = LoggerService.getLog();
LoggerService.log('Begin editing order #' + field.id);
}]);
.controller('OrderController', ['$scope', 'FOrder', 'LoggerService', function($scope, FOrder, LoggerService) {
FOrder.query(function(data){
$scope.orders = data;
});
$scope.log = LoggerService.getLog();
LoggerService.log('Begin editing order #' + field.id);
} <-- **you missed that bracket**
]);
Problem was in 'FOrder', 'LoggerService', i dont know why is important, but when i switch it to 'LoggerService', 'FOrder', all fine work.