ng-click does not work - javascript

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.

Related

ng-click on button that is ng-included

I have a problem. I'm trying to include a button that's on a html template page on to my index.html page. I do it like this
<ng-include src="'logout/logout.template.html'"></ng-include>
The page is:
<button type="button" class="btn btn-default btn-sm" ng-click="$ctrl.lala()">
<span class="glyphicon glyphicon-log-out" ></span> Log out
</button>
The problem is, the thing doesn't work. It won't access the ctrl function. As I read, ng-include doesn't work well with other angular directives so my question is, how else can I include my button template in the index.html without copy pasting the code because it's connected to a componenet an dservice so I can't break it.
The componenent:
'use strict';
angular
.module('logout')
.component('logout', {
templateUrl: 'logout/logout.template.html',
controller: ['$scope', '$location', '$localStorage', 'Logout',
function LogoutController($scope, $location, $localStorage, Logout) {
this.lala = function () {
console.log("doing logout");
}
}
]
});
I know it sounds like an overkill, but I would just create another component for it. If lala() is the function that actually logs the user out then it's best to include that in the component too, so you don't have to repeat it in every parent component.
Take a look at this jsfiddle for a complete sample. I wrote everything in the html, but I copied the important part below:
https://jsfiddle.net/6cjd5ggq/1/
<logout></logout>
angular.module('logoutapp')
.controller('logoutController', logoutController)
.component('logout', {
// you can use templateUrl, but it's easier this way in jsfiddle
template: `<button type="button" class="btn btn-default btn-sm" ng-click="$ctrl.lala()">
<span class="glyphicon glyphicon-log-out"></span> Log out
</button>`,
controller: 'logoutController'
});
function logoutController() {
this.lala = function() {
alert("logout!");
};
}

How do I get $emit to controller from directive built html

I'm having difficulty figuring this out. I have a directive building html from promise data. For each row, it's adding buttons for CRUD operations. I do not know how to get the button event to trigger in my controller. Regardless of how my controller is set up, how can I get the event to register in my controller? I am currently trying $emit, but nothing seems to happen.
Directive generated html:
controls = controls+'<button type="button" data-tooltip-placement="bottom" data-tooltip="'+action.name+'" ng-click="$emit(&apos;'+action.broadcaster+'&apos;,'+rowId+')" name="'+action.name+'" class="btn btn-xs btn-default ng-scope"><i class="'+action.icon+'"></i> </button>'
How it looks in Chrome tools:
<button type="button" data-tooltip-placement="bottom" data-tooltip="delete" ng-click="$emit('removeOrgCourse',134)" name="delete" class="btn btn-xs btn-default ng-scope"><i class="fa fa-trash-o"></i> </button>
and my controller listener:
$scope.$on('removeOrgCourse', function( event, data ){
console.log(data);
});
UPDATE:
Just changed the ng-click to console.log("click") and nothing happened. So the issue is that ng-click is not registering;
While you can use events in angular to achive that, one other option is to use & expression scope binding to pass controller method to directive. Example code (from egghead.io)(see working code at jsbin):
<div ng-app="phoneApp">
<!-- we've replaced the use of $scope with the preferred "controller as" syntax. see:http://toddmotto.com/digging-into-angulars-controller-as-syntax/ -->
<div ng-controller="AppCtrl as appctrl">
<div phone dial="appctrl.callHome(message)"></div>
<div phone dial="appctrl.callHome(message)"></div>
<div phone dial="appctrl.callHome(message)"></div>
</div>
Controller:
app.controller("AppCtrl", function() {
var appctrl = this;
appctrl.callHome = function(message) {
alert(message);
};
});
And directive:
app.directive("phone", function() {
return {
scope: {
dial: "&"
},
template: '<input type="text" ng-model="value">' +
'<div class="button" ng-click="dial({message:value})">Call home!</div>'
};
});
Maybe you have to use $broadcast, depends if the controllers are on the same level or who's over who.
Working with $scope.$emit and $scope.$on
http://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/
in the secon link you can put the $emit and $broadcast in the same controller and see whad do you catch in you $on

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

Controller is not defined

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){...}

How can you pass a bound variable to an ng-click function?

I have a simple delete button that will accept a string or number but won't accept an ng-model variable ( not sure if that's the correct terminology ).
<button class="btn btn-danger" ng-click="delete('{{submission.id}}')">delete</button>
Which generates:
<button class="btn btn-danger" ng-click="delete('503a9742d6df30dd77000001')">delete</button>
However, nothing happens when I click. If I hard code a variable then it works just fine. I assume I'm just not doing things the "Angular" way, but I'm not sure what that way is :)
Here's my controller code:
$scope.delete = function ( id ) {
alert( 'delete ' + id );
}
You don't need to use curly brackets ({{}}) in the ng-click, try this:
<button class="btn btn-danger" ng-click="delete(submission.id)">delete</button>
The ngClick directive binds an expression. It executes Angular code directly (as ngIf, ngChange, etc.) without the need of {{ }}.
angular.module('app', []).controller('MyCtrl', function($scope) {
$scope.submission = { id: 100 };
$scope.delete = function(id) {
alert(id + " deleted!");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="MyCtrl">
<button ng-click="delete(submission.id)">Delete</button>
</div>

Categories

Resources