Passing parameter to ng-click directive, within custom directive - angularjs

I'm using ng-repeat in the template for a custom directive as follows:
<li ng-repeat="image in images">
<img ng-src="{{image.url}}" ng-click="togglePhoto({{$index}})">
</li>
When rendered on the page the source looks like
<li ng-repeat="image in images" class="ng-scope">
<img ng-src="http://example.com/example.jpg" ng-click="togglePhoto(1)" src="http://example.com/example.jpg">
</li>
I have the function togglePhoto defined in my directive. Without the {{index}} parameter being passed in it works and the function is called. With the index, it doesn't fire.
How do I get the index of the photo clicked into the togglePhoto function?

Figured this out. Hope it helps anyone else stuck on it.
Firstly this
ng-click="togglePhoto({{$index}})"
Should be
ng-click="togglePhoto($index)"
Braces not needed!
Secondly I found that you can pass the event object into the click function eg
ng-click="togglePhoto($event)"
Then catch that event and find out what element trigged it in your click function
$scope.togglePhoto = function(e)
{
console.log(e.currentTarget)
}

I think that the issue is that you are using the double curly braces inside of the ng-click, and angular doesn't like that.
Try changing your repeater to this (note there are no curly braces around $index):
<li ng-repeat="image in images">
<img ng-src="{{image.url}}" ng-click="togglePhoto($index)">
</li>
I also put together a working jsfiddle to show that this works.
http://jsfiddle.net/n02ms8s0/4/

Related

ng-click - hide all other div that isn't this $index within ng-repeat

What i'm trying to do is similiar to an accordion.
Simple put
i have an ng-repeat with an <a> tag that once clicked show another div called "Printpanel" nested inside it within ng-show.
If the user cick to another <a> tag, i want to hide all other div showed before, and open only to that one related.
I am using $index to trigger the specific div.
Here what i have done:
<div ng-repeat="product in $ctrl.Products">
<a href="#" ng-click="showDetails = $index;>CONFIGURE</a>
<div class="Printpanel ng-hide" ng-show="showDetails == $index" ng-hide="showDetails != $index">
</div>
it seems that ng-hide is not recognized... Anybody have an idea?
You don't need to use ngShow + ngHide: one is enough.
<div class="Printpanel ng-hide" ng-show="showDetails == $index">
You can use ng-if also:
<div class="Printpanel" ng-if="showDetails == $index">
EDIT:
due to scope inheritance problem, you are not able to set showDetails variable. use $parent for that.
working example:
<div ng-repeat="product in $ctrl.Products">
CONFIGURE
<div class="Printpanel" ng-if="$parent.showDetails == $index"> </div>
</div>
seems you have missed closing double quotes here ng-click="showDetails = $index;
Also either of one you need to use ng-show/ng-hide/ng-if = expression

How to evaluate a template from a controller?

I've got this template:
<div class="container-fluid">
<div class="row">
<div class="col-xs-12" ng-repeat="product in ad.products">
<a href="{{product.link}}">
<h1>{{product.title}}</h1>
<img src="{{product.src}}">
<p>{{product.description}}</p>
<h5>{{product.price}}</h5>
</a>
</div>
</div>
</div>
From my controller I need to evaluate this template so that it checks how many products that have been selected and then it interpolates each product's values into the template. After that is done I also need to remove the ng-repeat so it doesn't fire an error in the external pages that will use this where angular is not present. However I'd figure that I'd just use a regex to look up the ng-repeat and everything in the expression and then remove it.
I've been looking at $interpolate and $compile but I can't figure out how to work with them from my controller so that it does what I want. This is because when I use these on my template and then console log the template value it's a function with a whole lot of nonsense in it.
So doing this:
ad.html = $compile(res.data, $scope);
Generates something like this:
function(b,c,d){rb(b,"scope");e&&e.needsNewScope&&(b=b.$parent.$new());d=d||{};var h=d.parentBoundTranscludeFn,k=d.transcludeControllers;d=d.futureParentElement;h&&h.$$boundTransclude&&(h=h.$$boundTr…
Can someone shed some light on how to achieve what I want?
Your are using $compile function in wrong way, you should call $compile(html) function by passing $scope parameter like below.
var compiledDOM = $compile(res.data)($scope);//then do append this DOM to wherever you want
ad.html = compiledDOM.html(); //but this HTML would not make angular binding working.

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

Setting ng-click in ng-repeat dynamically

I have a lot of data within ng-repeat. It looks like table with many rows and columns. I want to put ng-click directive on some of cell of table.
Can i put some condition before ng-click directive? If this condition is true - I want to put the directive, otherwise - not to put.
I think you should just put the directive in there and pass it a condition as a parameter which returns boolean. In the directive compile function check if your parameter is right and decide from there what you load.
Maybe this is what you were looking for?
<ul class="menuItems">
<li ng-repeat="item in menuItems">
<div ng-if="item.type == 'link' ">
{{item.name}}
</div>
<div ng-if="item.type == 'function' ">
<span ng-click="function(item.command)" title="item.description">{{item.name}}</span>
</div>
</li>
</ul>

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