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

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>

Related

Call function within object as parameter for a directive

currently I'm extending my application, so I can give a directive (which generates a table grid) an object for additional buttons to show (for adding other other actions).
Now I can show the button but I need to execute some code as function which should be apply for a click on that button.
The object itself contains strings and function in a mixed way, like this:
<tablegrid
table="flavorings"
additional-buttons="[{name: 'add', onclick: 'function(){ }', icon: 'fa fa-plus'}]"
show-actionbutton="true"
show-rating="true"
show-search="true"
show-rowcheckbox="true"
show-header="true">
</tablegrid>
My directive template looks like this:
<button ng-repeat="aB in additionalButtons" class="btn btn-primary" ng-click="ab.onclick" type="button">
<i ng-class="aB.icon" ng-show="aB.icon != ''" aria-hidden="true"></i>
<span>{{ 'TABLEGRID_'+aB.name | uppercase | translate }}</span>
</button>
How can I execute the onclick-function?
You can directly call a function of an object of the scope in your view with:
ng-click="yourObject.functionName(parameters)"
Don't forget the parenthesis in the function call even if there is no parameters
Here is a demo of how it works:
var app = angular.module('myApp', []);
app.controller('MyCtrl', function($scope) {
$scope.additionalButtons = [
{'name': 'First',
'onclick': function() {alert('1')}
},
{'name': 'Second',
'onclick': function() {alert('2')}
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<button ng-repeat="ab in additionalButtons" ng-click="ab.onclick()">Click {{ab.name}}</button>
</div>

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

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.

AngularJS remove last element of array in scope

I have my controller in Angular which contains an array and a delete method
function($scope, $http){
$scope.arrayOfObjects = [];
$scope.remove = function(obj){
var i = $scope.arrayOfObjects.indexOf(obj);
if( i > -1 ){
$scope.arrayOfObjects.splice(i, 1);
}
}
// Some other things
}
HTML
<a href ng-repeat="(key, obj) in arrayOfObjects track by $index">{{obj.id}}
<button type="button" role="button" class="btn btn-default" ng-click="remove(obj)">
<i class="fa fa-trash"></i>
<span>Delete</span>
</button>
</a>
Now all works well when I delete an object other than the last. When the user presses on the delete button for the last object, the page gets redirected to localhost:3000/# which is not mapped to anything and I get a blank page.
Has anyone encountered such behavior?
While the other answers are addressing your link / redirect issue, which would be solved by not having additional clickable items inside an anchor tag, the bigger problem is that you're using the wrong syntax for iterating over the objects of an array.
To iterate over an array you want this:
ng-repeat="obj in arrayOfObjects"
The syntax you're using is for iterating over the properties of one single object. Where key and value are the arguments passed to your repeater
ng-repeat="(key, value) in object"
Most likely what you want is something like this:
<div ng-repeat="obj in arrayOfObjects">
{{obj.id}}
<button ng-click="remove(obj)">Delete</button>
</div>
codepen
You can use 'filter' to return to original scope all itens that you want, just like that:
$scope.remove = function (objs) {
$scope.objs = objs.filter(function (obj) {
//Here you remove the item you do not want
return obj;
});
};
Html:
<button class="btn btn-danger btn-block" ng-click="remove(objs)">Delete</button>
Last element can be removed by using pop() and returns that element like $scope.arrayOfObjects.pop()
angular.module('app', [])
.controller('mycontroller', function($scope) {
$scope.arrayOfObjects = [{ id: 1 }, { id: 2 }, { id: 3 }]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="mycontroller">
<button ng-click="arrayOfObjects.pop()">remove in inline</button>
<ul>
<li ng-repeat="myobj in arrayOfObjects">{{myobj.id}}</li>
</ul>
</div>

Categories

Resources