Remove parent li after click child image - angularjs

I want to remove the parent li when I click on the child image using angular. Here's what I have so far:
View
<ul class="cg-tag-list">
<li ng-repeat="tag in list">
<span>{{tag}}</span>
<img src="" ng-click="fnRemoveTag()"/>
</li>
</ul>
JS
//Remove Tag
$scope.fnRemoveTag = function () {
// Put Code here
}

pass the tag to the fnRemoveTag function;
<ul class="cg-tag-list" >
<li ng-repeat="tag in list">
<span>{{tag}}</span>
<img src="" ng-click="fnRemoveTag(tag)"/>
</li>
</ul>
$scope.fnRemoveTag = function (tag) {
// get the index of the tag which we are going to remove
var index = $scope.list.indexOf(tag);
// remove that tag from the `list` array
$scope.list.splice(index, 1);
//this will automatically update the dom for you
}
here is a DEMO
and note that you can pass the $index of the instead of tag like
<img src="" ng-click="fnRemoveTag($index)"/>
and remove the element in controller as,
$scope.fnRemoveTag = function(index) {
// remove that tag from the `list` array
$scope.list.splice(index, 1);
//this will automatically update the dom for you
}
example DEMO
if you don't use the orderBy in the ng-repeat then use the $index other vise use the tag, because if you use orderBy it will sort the array according to sort description and when you pass the $index it may not the correct index of $scope.list.
for EX:
say you have array like $scope.list = [3, 2, 1]; and you need to ng-repeat this with order by
<li ng-repeat="tag in list | orderBy:tag">
after the orderBy, ng-repeat will repeat the sorted array, but actually $scope.list remain as before & it will not gonna sort only the repeat order gets change.
so $index is the ng-repeat's index and its not represent the index of $scope.list, if you do not use the orderBy then both will be same.
then when you try to remove from the $scope.list with the passed $index it will may not remove the correct element.
see this DEMO
try to remove first one and note that it actually remove the last one. because we pass the $index as 0 to the function and remove the 0th index element of the $scope.list which has value of 3.
hope that makes sense.

View
<ul class="cg-tag-list" >
<li ng-repeat="tag in list">
<span>{{tag}}</span>
<img src="" ng-click="fnRemoveTag(tag)"/>
</li>
</ul>
JS
//Remove Tag
$scope.fnRemoveTag = function (listItem) {
var index = $scope.list.indexOf(listItem);
if (index > -1) {
$scope.list.splice(index, 1);
}
}

if you have jQuery you can use this:
var li = $(this).closest("li");
li.parent().remove(li);

Simply put $index as function parameter then use array splice method.
View
<ul class="cg-tag-list" >
<li ng-repeat="tag in list">
<span>{{tag}}</span>
<img src="" ng-click="fnRemoveTag($index)"/>
</li>
</ul>
Javascript (don't use orderBy filter in this purpose)
$scope.fnRemoveTag = function (index) {
$scope.list.splice(index, 1);
}

Related

$first in ng-repeat with an ng-if

I have the following:
<li ng-repeat"item in items" ng-if="item.type && item.type=='image'">
<span ng-class="{'selected':$first}">{{item.title}}</span>
</li>
What I'm trying to do is display all item Titles only if it's of type image, and have the first item have the class selected.
The issue comes with the ng-if. If the first item is not of type image, then the actual first item shown does not have the selected class.
How do I update this?
You could create a new list that only has images. Then ng-repeat over that:
$scope.onlyImages = $scope.items.filter(function(item) {
return item.type && item.type === 'image';
});
<li ng-repeat"item in onlyImages">
<span ng-class="{'selected':$first}">{{item.title}}</span>
</li>
You could also do this in the template with a filter, but it would be more expensive since it runs on each digest cycle.

Removing element from ng-repeat does not allow to remove or hide element from DOM

I have below code to display records using ng-repeat:
<div class="gallery">
<div ng-cloak
ng-repeat="photo in photos| orderBy:'-id'"
ng-mouseLeave = "delete_btn = !delete_btn"
ng-mouseEnter = "delete_btn = !delete_btn"
class="gallery_block"
id="photo_block_[[photo.id]]">
<span title="delete photo" ng-show="delete_btn" class="delete_btn_span" rel="[[photo.id]]" id="delete_photo_[[photo.id]]">
<img src="{{asset('frontend/images/cross_icon.png')}}">
</span>
<p>
<a href="javascript:;">
<img ng-click="showImagePopup([[photo.path_popup_thumbnail]]);" src={{$public_path}}./image.php?width=149&height=109&cropratio=2:1.4&image=[[photo.path_popup_thumbnail]] alt="">
</a>
{{--<span> </span>--}}
</p>
</div>
</div>
I have to delete records for that I first have to call a function using $http and then I remove element from photos array:
var index = $scope.photos.indexOf($('#photo_block_'+id));
$scope.photos.splice(index, 1);
Then I remove element from DOM:
$('#photo_block_'+id).remove();
Update
I have called deletePhoto function using jqyery like below:
$(".gallery").on('click','span.delete_btn_span',function()
{
$scope.deletePhoto($(elem), $(elem).attr('rel'));
});
deletePhoto function further do all the work of deleting elements etc.
But it does not remove element. Where as all the selectors are fine.
Is removing element from photos array causing problem?
With angular JS, you have to deal with data. So you should put an ng-click="delete(photo)" on your span.
and create a method in your controller :
$scope.delete = function(photo) {
// delete froms scope.photos here...
}
to delete the photo from the list.
Your code does not work because $scope.photos.indexOf($('#photo_block_'+id)) surely return -1, because you're looking for $('#photo_block_'+id), which is a jquery object in a list of simple json object (i suppose).
So the splice method does anything, and the $scope.photos list remain unchanged, so the view is not changed, because it's build from the list by the ng-repeat directive.
ps: you should never manipulate dom element from controller, if you need to do that, you should create directive.

Angularjs ng-repeat dynamic property

<div (ng-repeat='item in items') >
{{item.name}} //works
{{item["name"]}} // works
</div>
how do i repeat item[property] dynamically without using ".name" or ['name']?
To dynamically go through properties, you're going to need to call Object.keys(item) and then iterate through them. It's best to prune your data from within your controller, to minimize the finagling you'll need to do within your HTML.
If you do want to try to do this within your HTML-Angular structures, you could define:
$scope.returnAllKeyValues = function(obj){
var x = Object.keys(obj),
arr = [];
for(var i = 0; i<x.length; i++){
arr.push(obj[x[i]]);
}
return arr;
}
What this function does is it takes in your JSON object, then parses through it and collects all the values for every key within it.
Then, within your HTML, you can write something like this:
<h3>FIFA Mactch Summary:</h3>
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in items">
<span ng-init="keyValues = returnAllKeyValues(item)">
<span ng-repeat="keyValue in keyValues">{{key}} </span>
</span>
</li>
</ul>
</div>
Here you see, within your original ngRepeat, we initialized the array keyValues with all the values from item's keys via the function defined above. Then, ng-repeat through that, and you have everything printed without knowing what they are.
Here is a Fiddle with it working:
http://jsfiddle.net/RkykR/2771/
This was what i was looking for....Thanks
https://www.codementor.io/debugging/4948713248/request-want-to-use-values-in-nested-ng-repeat

Get $index after filter

I have a small image gallery which has a search box and when the user clicks on a image it'll open a lightbox with that same image.
Basically I'm passing the $index to a function which opens the item in $scope.list[lb.index].
my code:
HTML
<input type="text" ng-model="query.name" />
<ul class="list" ng-show="list.length>0">
<li ng-repeat="item in list | filter:query">
<a class="img" ng-style="{'background-image':'url(/uploads/<%item.image%>)'}" ng-click="openLB($index)"></a>
</li>
</ul>
<div class="lightbox" ng-if="lb.show">
<a class="prev" ng-show="list.length>1" ng-click="changeItemLB(lb.index, 'prev')"></a>
<a class="next" ng-show="list.length>1" ng-click="changeItemLB(lb.index, 'next')"></a>
<div class="holder">
<img ng-if="list[lb.index].image.length" ng-src="/uploads/<%list[lb.index].image%>" />
</div>
</div>
Angular
$scope.openLB = function(index) {
$scope.lb.show = true;
$scope.lb.index = index;
};
$scope.changeItemLB = function(index, action) {
var tot = $scope.list.length-1,
goto = 0;
if(action=='prev') goto = index==0 ? tot : index-1;
if(action=='next') goto = index==tot ? 0 : index+1;
$scope.openLB(goto);
}
The problem is after the user filters the results (search input), the click still maintains the index from the list without the filter which makes the lightbox open the wrong image. Does anyone know how to solve this?
Thanks
Pass object instead of index
Suppose you have 5 item in your list
filter showing two result.
If you click then $index value will be your current view's index
but your list still then have 5 item.
Try like this
<a class="img" ng-style="{'background-image':'url(/uploads/<%item.image%>)'}" ng-click="openLB(item)"></a>
controller
$scope.openLB = function(item) {
var index = $scope.list.indexOf(item);
$scope.lb.show = true;
$scope.lb.index = index;
};
EDIT
How to get Filtered result
Try like this
view
<li ng-repeat="item in filtered= (list | filter:query)">
controller
$scope.filtered=[];
Now you can get yor filtered list from $scope.filtered

AngularJS , small trick

I've got one question . Is there anybody how has idea how to invoke function in controller only for the first li object in ul when ul has a ng-repeat?
Lets say ive got function in my controller like:
var init = function () {
var a = this;
};
And my ul repeater seams like lets say:
<ul ng-repeat="up in userpartners" ng-click="setSelected(this);">
<li>
{{up.id}}
</li>
</ul>
And I want to invoke init function with parameter 'this' which will be first 'li' item. Only for the first li i want to set something.
You can do it like this:
<ul ng-repeat="up in userpartners" ng-init="init(up, $first);">
<li>
{{up}}
</li>
</ul>
And in the controller:
$scope.init = function (item, isFirst) {
if (isFirst) {
alert(item);
}
};
Fiddle Example
See here check if $index is zero or $first is true.
But there's already a single LI inside your UL.
I believe you mean:
<ul>
<li ng-repeat="up in userpartners" ng-init="$first && setSelected(up)">
{{up.id}}
</li>
</ul>
or
<ul ng-init="setSelected(userpartners[0])">
<li ng-repeat="up in userpartners">
{{up.id}}
</li>
</ul>
See the difference? We want to repeat the children, not the whole list.
Although I believe it wouldn't be a good practice to have this call on a view. I'd put it inside a controller, the call itself.

Resources