pasing parameter to ng-click function within ng-repeat - angularjs

I am using onclick="window.open('tel:+94777122240')" in my angular ionic application. which lets the user to open dial box when onclick. i am trying to pass values to the onclick function withing ng-repeat. but the ng-repeat values doesnt pass to fucntion
i have used this method to solve it. but it does not work
<div ng-repeat="branch in branches">
<a ng-click="window.open('tel:branch.telephone')" class="button">Call Now</a>
</div>

Angular expressions are evaluated against the scope.
Try to move the ng-click function to the controller:
$scope.open = function(branch) {
window.open('tel:' + branch.telephone);
}
<div ng-repeat="branch in branches">
<a ng-click="open(branch)" class="button">Call Now</a>
</div>

Related

Angular 1.5 Binding ng-repeat created controls?

Angular 1.5
In an ng-repeat I create a button that will display a Bootstrap popup with anchor links.
How do I bind the onAction call so that it calls my $scope.onAction() function ? (onAction() is not bound to $scope.onAction().)
<div ng-repeat="item in model.Holdings track by $index" bs-popover>
<button class="popoverBtn"
data-content="<a ng-click='onAction(1)'>Buy</a>...and more"
click me to show popup
</button>
</div>
Here's my directive that turns the Bootstrap popover on:
app.directive('bsPopover', function () {
return function (scope, element, attrs) {
element.find(".popoverBtn").popover({ placement: 'auto', html: 'true' });
????COMPILE GOES HERE???////
};
});
It sounds like you want the onAction method to take an item identifier.
Perhaps something like <a ng-click='onAction(item.id)'>Buy</a> ??
From what I recall, you are in the scope of the controller that stores the data. If you have nested ng-repeats, look into $parent.
If you are looking to pass the index value of an item into your function on a click event, you need only pass it $index instead of an explicit value. For example:
<div ng-repeat="item in model.Holdings track by $index">
<button class="btn btn-primary"
data-content="<a ng-click='onAction($index)'>Buy</a>...and more">
click me to show popup
</button>
</div>
UI-Bootstrap project seems to have simple to use controls for Angular + Bootstrap.
https://angular-ui.github.io/bootstrap/
This worked

AngularJS - One controller on two sibling DOM elements

I'm trying to do a very simple thing. I'm displaying a list of values with Edit links beside them. Clicking the edit link reveals a form that lets you update the value.
(I've simplified the question so the items just have one field "name". My actual use case has more fields, but is canonically equivalent.)
I've run into something that looks like a bug in Angular, but given my limited experience with it, I'm not so sure. Here's how I'm trying to do it:
<div ng-repeat-start="item in items" ng-controller="ItemCtrl as ctrl" ng-hide="ctrl.isEditing">
<span>Name: {{item.name}}.</span>
<a href='#' ng-click='ctrl.startEditing()'>Edit</a>
</div>
<div ng-repeat-end ng-show="ctrl.isEditing">
<input type='text' ng-model='item.name'/>
<a href='#' ng-click='ctrl.save()'>Save</a>
</div>
My controller looks like this:
app.controller('ItemController', function() {
this.isEditing = false;
this.startEditing = function() { this.isEditing = true; }
this.save = function() { this.isEditing = false; }
});
Clicking on Edit link calls the right controller function, and the first div hides. But the second div does not hide.
When I rearrange the code to look like this (essentially wrapping the two divs with a wrapper element), all is well.
<div ng-repeat="item in items" ng-controller="ItemCtrl as ctrl">
<div ng-hide="ctrl.isEditing">
<span>Name: {{item.name}}.</span>
<a href='#' ng-click='ctrl.startEditing()'>Edit</a>
</div>
<div ng-show="ctrl.isEditing">
<input type='text' ng-model='item.name'/>
<a href='#' ng-click='ctrl.save()'>Save</a>
</div>
</div>
Any idea what is technically wrong with the first version? Note that the <input> boxes do get populated with the right values from item.name.
PS: There's a reason why I'm trying to keep the two divs siblings: in my use case, they are actually implemented as two trs which are supposed to appear right below each other in a table.
It's not a bug from angular but it is quite logical.
<div ng-repeat-start="item in items" ng-controller="ItemCtrl as ctrl" ng-hide="ctrl.isEditing">
<span>Name: {{item.name}}.</span>
<a href='#' ng-click='ctrl.startEditing()'>Edit</a>
</div>
<div ng-repeat-end ng-show="ctrl.isEditing">
<input type='text' ng-model='item.name'/>
<a href='#' ng-click='ctrl.save()'>Save</a>
</div>
If you see the above code you have injected controller only to the first div so obviously sibling div doesn't know what is ctrl or ItemCtrl until and unless you do as in you second way.
So if you want to achieve it as sibling, if you are using routing then add the controller attribute in your route path.
So that the controller will be active for that entire template and you can achieve what you want.
Hope it helps.
Thats because controller has its own scope. When you placed controller ONLY on your first div controllers' scope is limited to only this one div. When you wrapped both your divs inside another and place controller on wrapper, controllers' scope now is all that inside this wrapper. So in this case this works fine and this is not the angular bug

AngularJS - ui-bootstrap accordion - using ng-controller inside ng-repeat doesn't work

I'm trying to construct an accordion list that shows more details when the accordion expands. Here is a simplified version of the template:
<body ng-controller="MainController as main">
<accordion>
<accordion-group ng-repeat="r in main.results" ng-controller="DetailsController as d">
<accordion-heading ng-click="d.getDetails(r.id)">
{{r.name}}
</accordion-heading>
<ul>
<li ng-repeat="v in d.details">{{v.detail}}</li>
</ul>
</accordion-group>
</accordion>
</body>
The DetailsController initially has an empty details array, but when the function getDetails() is called, that array is populated by a service (detailsService is simply an abstracted $resource call). This part works when not being applied to an accordion, but in this specific situation, nothing happens with the accordion heading is clicked. See below:
app.controller('DetailsController', function(detailsService) {
var vm = this
var details = []
var detailsPopulated = false
var getDetails = function(id) {
console.log('getDetails()')
if (!vm.detailsPopulated) {
console.log('Getting details')
detailsService.get({id: id}, function(data) {
vm.details = data.results
vm.detailsPopulated = true
});
}
}
return {
details: details,
getDetails: getDetails
}
});
This controller works in other cases, but for some reason, the ng-click on the accordion header does not invoke the getDetails function at all - if it did, I would see "getDetails()" in the console, since that is the first statement of the getDetails function.
Even simpler: setting up a controller with mock "details" doesn't work.
app.controller('DetailsController', function() {
var details = [{detail: 'Test'}]
return {
details: details
}
});
Template:
<body ng-controller="MainController as main">
<accordion>
<accordion-group ng-repeat="r in main.results" ng-controller="DetailsController as d">
<accordion-heading>
{{r.name}}
</accordion-heading>
<ul>
<li ng-repeat="v in d.details">{{v.detail}}</li>
</ul>
</accordion-group>
</accordion>
</body>
Not even this simplified example with the service and ng-click removed works.
Can anyone advise a solution? I am also trying to accomplish this using the "controller as" technique instead of using $scope everywhere.
You can not bind ng-click to <accordion-heading> beacause ui.bootstrap will use different DOM for heading. You can take a look at developer console to see what ui.bootstrap translate <accordion-heading> into DOM.
<div class="panel-heading">
<h4 class="panel-title">
<span class="ng-scope ng-binding">Header 1</span>
</h4>
</div>
I think you want to dynamically load the content of accordion. One way to achieve this is to $watch when the accordion is opened and perform loading. I have created this fiddle to demonstrate the idea. Something you must notice :
You can not put ng-controller inside accordion-group because it will raise error multiple directive asking for isolated scope. This is beacause <accordion-group> is an isolated scope and angular will not allow two scope : one from controller scope and one from directive isolated scope to bind into the same html. Reference. One way to work around it is to put a div with ng-controller and ng-repeat outside accordion-group
<div ng-repeat="r in main.results" ng-controller="DetailsController as d">
<accordion-group>
...
</accordion-group>
</div>
You can add attrs is-open to accordion-group and $watch for its change and perform loading. Accordion directive will change is-open value when you open or close the accordion.
Hope it helps.

AngularUI - Accordion trigger a method inside the template using ng-click

I'm using the AngularUI bootstrap library with templates. I'm wainting to call a custom method inside the template and I was wondering what I need to do in order to get this working? I guess what I'm wanting is to replace the ng-click="isOpen = !isOpen" with my own custom method if possible.
Thanks in advance.
<div class="panel panel-default">\n <div class="panel-heading">\n
<h4 class="panel- title">\n
<a class="accordion-toggle" ng-click="isOpen = !isOpen" accordion- transclude="heading">{{heading}}</a>\n </h4>\n
</div>\n
<div class="panel-collapse" collapse="!isOpen">\n <div class="panel-body" ng-transclude></div>\n
</div>\n</div>
Since clicking on the toggle changes the value of isOpen,
you can watch it and apply your logic without changing the ng-click attribute
$scope.$watch('isOpen', function(value) {
if (value) {
// your code
}
});

ng-click not working inside of ng-include

I have a site that links to a component through ng-include:
<div id="tracklist">
<ng-include src="'partials/tracks.html'">
</ng-include>
</div>
the partial looks like this:
<div ng-controller="TracklistController">
<div ng-repeat="track in tracks">
<a ng-click="$('body').css('background-color', 'red')" href="#/tracks/{{ track.id }}" class="track-link" data-audio-source="{{ track.source }}">{{ track.trackNumber + " - " + track.title }}</a>
</div>
</div>
It renders fine and works, but my ng-click event does not fire for some reason. Note that changing the body background color is just an obvious test to see if it's failing. I've tried it with my actual function (declared globally when the document loads for now), and I've also tested with console.log. None of it works, so clearly ng-click is just not working. Any ideas?
Make sure you put your function in the controller and assign it to the $scope.
<a ng-click="action();">
function TracklistController($scope){
$scope.action = function(){ ... }
}
ngClick doesn't accept arbitrary JavaScript or functions defined outside of Angular! ngClick accepts an AngularJS expression. For example, data-ng-click="foo()" will call foo on the current scope!

Resources