Controller is not defined - javascript

I'm trying to use the Angularjs-UI Modal into my application and I'm a little confused as to what goes where. I have a button for new groups which calls a model, the models controller is in another file. I'm trying to call the newGroupCtrl within the groupCtrl but it's returning undefined.
HTML for new group button:
<button type="button" class="delGroupBtn" ng-click="newGroup()">New Group</button>
In my groupCtrl I have this newgroup() function:
$scope.newGroup = function (){
var modalForm = '/Style%20Library/projects/spDash/app/partials/newGroup.html';
var modalInstance = $modal.open({
templateUrl: modalForm,
backdrop: true,
windowClass: 'modal',
controller: newGroupCtrl,
resolve:{
newGroup:function (){
return $scope.newGroup;
}
}
});
};
Then I've got my newGroup.html (the modal) which is where the user would enter the groups name, description, owner:
<div class="modal-header">
<form>
<label for="groupName">Group Name:
<input id="groupName" type="text" ng-model='newGroup.name'>
</label>
<hr>
<label for="groupDesc">Group Description:
<input id="groupDesc" type="text" ng-model='newGroup.desc'>
</label>
<hr>
<label for="groupOwner">Group Name:
<select id="groupOwner" type="text" ng-model=''></select>
</label>
<div class="modal-footer">
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
<button class="btn primary-btn" type="button" ng-click="newGroup()">Create</button>
</div>
</form>
</div>
Here's the newGroupCtrl:
spApp.controller('newGroupCtrl',
function newGroupCtrl($scope, $modalInstance){
$scope.newGroup = {
name:null,
desc:null
};
$scope.submit = function(){
console.log('creating new group');
console.log(newGroup);
$modalInstance.dismiss('cancel');
}
$scope.cancel = function (){
$modalInstance.dismiss('cancel');
};
$modalInstance.result.then(function (){
groupService.newGroup($scope.newGroup);
}, function (){
console.log('No new group created.');
});
}
);
I've injected the group and newGroup controllers with my group service which is where I'm trying to get the information from the model to the groupService function to make the AJAX call to my server and create the new group. It seems like I'm repeating myself in both controllers with the $model.open({})
Here's a plunker

When controller is defined as part of the angular module (using .controller() method) than it must be referenced as a string.
When controller is defined as a simple JS function, then it must be referenced through a variable.
In you modal configuration object, you referenced newGroupCtrl as a variable, not as a string.
...
controller: newGroupCtrl,
...
vs
...
controller: 'newGroupCtrl',
...
But your controller is defined with angular.module().controller():
spApp.controller('newGroupCtrl',
function newGroupCtrl($scope, $modalInstance){...})
To fix, you need to put the name of the controller in quotes OR define the controller as a simple standalone JS function.
So, it's either this:
...
controller: 'newGroupCtrl',
...
spApp.controller('newGroupCtrl',
function newGroupCtrl($scope, $modalInstance){...})
OR this:
...
controller: newGroupCtrl,
...
function newGroupCtrl($scope, $modalInstance){...}

Related

Access to method in the same .factory in Angular.js

I run the factory, and excecute the function "fn_generarPopupConfirm()" in any controller.
in this method, I have now created a template. This template has a buton that has an ng-click, which calls an existing function inside the same factory. In my example I have this:
<button type="submit" class="btn btn-primary" ng-click="fn_confirmar()">
How can I do it to call it ("oElim.fn_confirmar()")?, without needing to define a function in which I define a $scope object, to call the function needed. this function is present in the same factory.
controller: function($scope){
$scope.fn_confirmar=function(){
oElim.fn_confirmar();
}
},
I need the function to be called directly "oElim.fn_confirmar()" with the ng-click event. it's possible?
this is my factory.
.factory('eliminar', function($state,$rootScope,$uibModal,popup_generico) {
var oElim= {};
oElim.fn_generarPopupConfirm = function(objeto,array,titulo,contenido) {
$rootScope.modalInstances.push($uibModal.open({
template: '<form id="form_popup" class="form-horizontal"><div class="modal-header">
<h3 class="modal-title"><button type="submit" class="btn btn-primary"
ng-click="fn_confirmar()">
OK</button></div></form>',
controller: function($scope){
$scope.fn_confirmar=function(){
oElim.fn_confirmar();
}
},
backdrop: 'static'
}));
}
oElim.fn_confirmar = function(){
var index = oElim.array.indexOf(oElim.objeto);
oElim.array.splice(index, 1);
popup_generico.fn_CerrarModal();
}
return oElim;
})
I do not believe that this is possible within angular, as the template is a string that will be interpolated within the context of the controller, not the factory.
If you really want to have scope access to the oElim factory without injecting it into a controller, you could bind the oElim object directly to the $rootScope, giving you prototypal access to its methods within the template "$rootScope.oElim.fn_confirmar()" or equivalently just "oElim.fn_confirmar()" from any template you define in your angular app.
As I know it's not possible, but you can do the following:
controller: function($scope){
$scope.fn_confirmar = oElim.fn_confirmar;
},
or add the object to $rootScope
.factory('eliminar', function($state,$rootScope,$uibModal,popup_generico) {
var oElim= {};
$rootScope.oElim = oElim;
oElim.fn_generarPopupConfirm = function(objeto,array,titulo,contenido) {
$rootScope.modalInstances.push($uibModal.open({
template: '<form id="form_popup" class="form-horizontal"><div class="modal-header">
<h3 class="modal-title"><button type="submit" class="btn btn-primary"
ng-click="oElim.fn_confirmar()">
OK</button></div></form>',
controller: Function.prototype, //Just dummy function
backdrop: 'static'
}));
}
oElim.fn_confirmar = function(){
var index = oElim.array.indexOf(oElim.objeto);
oElim.array.splice(index, 1);
popup_generico.fn_CerrarModal();
}
return oElim;
})
or better, just used built-in angular event service
.factory('eliminar', function($state,$rootScope,$uibModal,popup_generico) {
var oElim= {};
oElim.fn_generarPopupConfirm = function(objeto,array,titulo,contenido) {
$rootScope.modalInstances.push($uibModal.open({
template: '<form id="form_popup" class="form-horizontal"><div class="modal-header">
<h3 class="modal-title"><button type="submit" class="btn btn-primary"
ng-click="$emit('fn_confirmar')">
OK</button></div></form>',
controller: Function.prototype, //Just dummy function
backdrop: 'static'
}));
}
oElim.fn_confirmar = function(){
var index = oElim.array.indexOf(oElim.objeto);
oElim.array.splice(index, 1);
popup_generico.fn_CerrarModal();
}
$rootScope.$on('fn_confirmar', oElim.fn_confirmar);
return oElim;
})

Access form from within Angular $mdDialog

I am using an Angular 1.5 Material Design $mdDialog in the recommended way, using controllerAs: "dialog". In the template I have a form: <form name="fooForm". Within the template I can access the form with no problem, e.g. ng-disabled="fooForm.$invalid || fooForm.$submitted".
But how do I access that form from within the $mdDialog controller? From what I read, I would expect to be able to do this:
const doFoo = () => {
if (this.fooForm.$dirty) {
Here this is the dialog controller.
But I get an error: TypeError: Cannot read property '$dirty' of undefined. And sure enough, if I put a breakpoint in the code, the controller has no fooForm property.
I've tried using $scope as well, but when I put a breakpoint in the code $scope has no fooForm property either.
Here's my dialog template:
<md-dialog aria-label="FooBar">
<md-toolbar>
<div class="md-toolbar-tools">
<h2>FooBar</h2>
<span flex></span>
<md-button class="md-icon-button" ng-click="dialog.cancel()">
<md-icon>close</md-icon>
</md-button>
</div>
</md-toolbar>
<form name="fooForm" ng-submit="dialog.ok()" novalidate>
<md-dialog-content>
<div layout="column" layout-padding>
<h2 class="md-headline">Foo</h2>
<div layout="row" layout-xs="column">
...
</div>
</md-dialog-content>
<md-dialog-actions>
<md-button class="md-primary" type="submit" ng-disabled="fooForm.$invalid || fooForm.$submitted">
OK
</md-button>
<md-button ng-click="dialog.cancel()">
Cancel
</md-button>
</md-dialog-actions>
</form>
</md-dialog>
How do I access a form in an $mdDialog from the dialog controller?
you need to assign the form to the Scope of the Controller. Do this by changing the form name from fooForm to dialog.fooForm.
<form name="dialog.fooForm" ng-submit="dialog.ok()" novalidate>
Scope existed and still exist disregarding controllerAs. When you use 'controllerAs xxx' that just mean - put my controller into scope and name it xxx. You can use them together:
function controller($scope) {
var vm = this;
vm.click = function() {}
$scope.click = function() {}
}
<button ng-click="xxx.click()" ...
<button ng-click="click()" ...
Now if you write ng-click="whatever();smth();"angular will use $parse(expression)(scope) to parse this expression.
Now you write form name="formName" -- angular will use $parse("formName").assign(scope, form); and put it to scope.
$parse is quite clever and can easily handle nested properties, to put form to your controller (as xxx): <form name="xxx.myForm"></form>
The form is not defined in your controller as a property and therefore you cannot access the form like if (this.fooForm.$dirty).
However you can easily pass it to your method:
const doFoo = (fooForm) => {
if (fooForm.$dirty) {
...
And in html:
ng-click="dialog.cancel(fooForm)"
Give your controller name when your $mdDialog initialize. see below code:
$scope.showDialog = function (ev) {
$mdDialog.show({
controller: 'myController',
templateUrl: 'template.html',
parent: angular.element(document.body),
targetEvent: ev,
clickOutsideToClose: false,
fullscreen: false // Only for -xs, -sm breakpoints.
})
.then(function (answer) {
$scope.status = 'You said the information was "' + answer + '".';
}, function () {
$scope.status = 'You cancelled the dialog.';
});
};
Make sure you put controller name in quotes when you create separate controller. like controller: 'myController'
if you want to pass a function then not quotes needed like controller: myController,
In html template use ng-submit="ok()" instead of ng-submit="dialog.ok()".
I have created a sample plnkr with your template and it is working fine. check here
EDIT :`
angular.module('BlankApp', ['ngMaterial']).controller('myController', function($scope, $mdDialog) {
$scope.ok = function () {
if ($scope.fooForm.$dirty) {
// do whatever you want
$mdDialog.hide("mesage");
}
};
});`

Angular-ui-bootstrap modal not showing data passed to it

I am trying to pass some model data into a modal window when it opens. Its in a $http.post success and also in failure then() with some different titles and button texts. I pass multiple data to it like:
//.then(){...//same as below }
,function (response){
$scope.PostRespData = response.data.message || 'Rq Failed';
$scope.pn = $scope.PostRespData.substring(53,63);
//(status=400) response modal string
$scope.name = 'Hey there!';
//modal options
$scope.opts = {
backdrop: true,
backdropClick: true,
dialogFade: false,
keyboard: true,
templateUrl : 'alreadyexists.html',
controller : ModalInstanceCtrl,
resolve: {}
};
$scope.opts.resolve.item = function() {
return angular.copy({name:$scope.name, errmsg:$scope.PostRespData, num:$scope.pn}); // pass name to modal dialo
}
//open the modal and create a modal Isntance
var modalInstance = $uibModal.open($scope.opts);
var ModalInstanceCtrl = function($scope, $uibModalInstance, $uibModal, item) {
$scope.item = item;
$scope.ok = function () {
$uibModalInstance.close();
};
$scope.cancel = function () {
$uibModalInstance.close();
}
My HTML template looks like
<div class="modal-header">
<h1>{{item.name}}</h1>
</div>
<div ng-controller="Nav" class="modal-body">
<p>{{item.errmsg}}
View {{item.num}}
</p>
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">Edit Current Details</button>
<button class="btn btn-warning" ng-click="cancel()">Edit {{item.num}}</button>
</div>
I get my modal and I also get the static data but data being passed to it does not reflect. I've spent the whole day trying to make this work.
Edit: Adding current output pic.
Please help me!
As pointed out by #charlietfl, it was a hoisting issue. To use the above code, move var ModalInstanceCtrl = func.. outside the button's ng-click call of $http.

ng-click does not work

I'm programming a single-page web application, mostly using the AngularJS framework, and am encountering a problem while using the ng-click directive.
This directive actually does nothing upon click. The linked method is not called (I can't debug it).
Below the code in question:
template file:
<div ng-controller="BonusCtrl as bonusManager">
<!-- [...] -->
<button style="margin-top: 5px"
class="btn btn-success" ng-click="add()"><i class="fa fa-plus"/> Règle de calcul</button>
<!-- [...] -->
</div>
controller:
idServerApp.controller('BonusCtrl', ['$scope', 'webService', 'math', 'DATERANGE_OPTIONS', function ($scope, webService, math, DATERANGE_OPTIONS) {
$scope.add = function() {
console.log('foo'); // no call
var newItem = {
brandId: undefined,
days: 0,
priceMinEVAT: 0,
bonus: 0
};
$scope.rules.push(newItem);
};
Do you have any idea of the problem?
Edit 1
I tried to replace bonusManager.add() by add() and BonusCtrl.add().
I then tried to replace $scope by this, or to remove the controllerAs.
Complete JSFiddle (using some of my services)
Edit 2
Thanks for your answers. I found the solution myself, and it was crappy.
I forgot a closing div tag in the HTML template, so the controller was not defined.
I get your code and made an running example with two cases.
First one using BonusCtrl
$scope.add = function () {...}
ng-click="add()"
And second with bonusManager
this.add = function () {...}
ng-click="bonusManager.add()"
For me it should works just fine. Please let me know if you have any other issues.
var app = angular.module('myapp',[]);
app.controller('BonusCtrl', ['$scope', function ($scope) {
$scope.add = function() {
console.log('Hey you\'ve just invoked add() function!'); // no call
var newItem = {
brandId: undefined,
days: 0,
priceMinEVAT: 0,
bonus: 0
};
};
this.add = function () {
console.log('You can invoke function using \' bonusManager.add()'); // no call
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<h1>NG-CLICK EXAMPLE</h1>
<div ng-controller="BonusCtrl as bonusManager">
<button style="margin-top: 5px"
class="btn btn-success" ng-click="add()"><i class="fa fa-plus"/>add()</button>
<button style="margin-top: 5px"
class="btn btn-success" ng-click="bonusManager.add()"><i class="fa fa-plus"/> bounsManager.add()</button>
</div>
</div>
However you can always use your
Check the working demo: JSFidde
You are using <div ng-controller="BonusCtrl as bonusManager">, so call it like:
<button style="margin-top: 5px" class="btn btn-success"
ng-submit="bonusManager.add()"><i class="fa fa-plus"/> Règle de calcul</button>
In the controller, define this.add = function() {... instead of $scope.add = function() {.... Because the keyword as will call a new BonusCtrl() under the hood.
If you use $scope than you don't need construction ControllerAs, just use
<div ng-controller="BonusCtrl">
and submit function ng-submit="add()"
Or if you want to use ControllerAs, than use "this":
<div ng-controller="BonusCtrl as bonusManager">
ng-submit="BonusCtrl.add()"
But in your controller have to be "this" instead of $scope:
`
this.add = function() {
`
Try it.
If you are using BonusCtrl as bonusManager then do as follows
Update bonusManager.add() in view and in controller write this.add instead of $scope.add() .
Otherwise just remove as bonusManager from ng -controller syntax .it will work fine.

Why is my angular binding read only in a bootstrap UI modal in an MVC5 project?

I am trying to pop up a modal to get some input, but the angular binding via ng-model seems to be read only. This is my modal markup:
<script type="text/ng-template" id="signatureWindow.html">
<div class="modal-header">
<h4 class="modal-title" id="myModalLabel">Signature Capture</h4>
</div>
<input type="text" width="100px" ng-model="theName" />
<div class="modal-footer">
<button ng-click="accept()" class="btn btn-primary">Accept</button>
<button ng-click="cancel()" class="btn btn-default">Cancel</button>
</div>
</script>
Then, I invoke this modal as follows:
$scope.getSignatureModal = function(signatureBase64) {
var modalInstance = $modal.open({
templateUrl: 'signatureWindow.html',
controller: 'SignatureModalController',
size: 'lg',
resolve: {
signatureData: function() {
return signatureBase64;
}
}
});
modalInstance.result.then(function(signatureData) {
alert('Signed');
signatureBase64 = signatureData;
}, function() {
alert('Canceled');
});
};
And the following controller code for the modal:
MlamAngularApp.controller('SignatureModalController', function($scope, $modalInstance, signatureData) {
$scope.base64 = signatureData;
$scope.thename = "NamesRus";
$scope.accept = function() {
debugger;
$modalInstance.close($scope.thename);
}
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
}
});
The modal pops up as expected, and the input has the initial value "NamesRus", but when I close the modal, invoking accept in the modal controller, $scope.thename still has it's initial value, not any new value I type when the modal is active. What could be wrong here?
NOTE: At the debugger breakpoint in accept, no matter what I type in the modal's input, theName still has the initial assigned value.
MORE: My Plunker for this works fine. It's when in-place, in an ASP.NET MVC5 project, that I get the strange behaviour.
I think that you mix up two differents scopes.
If you want several variables to be passed to and retrieved from the modal you have to mention them:
in the resolve attribute
resolve: {modalData: function (){return {signatureData:$scope.base64,name:$scope.theName}}}
pass modalData as dependencie to your controller
MlamAngularApp.controller('SignatureModalController', function($scope, $modalInstance, modalData)
update the modal controller $scope with modalData
$scope.signatureData = modalData.signatureData;
$scope.name=modalData.name;
invoke
$modalInstance.close({signatureData:$scope.base64,name:$scope.theName})
reassign the original $scope with the result of promise
modalInstance.result.then(function (data) {
$scope.base64 = data.signatureData;
$scope.thename=data.name;
}
take a look at this plunker forked from ui-boostrap modal orginal example: http://plnkr.co/edit/whLSYt?p=info

Categories

Resources