I have some angular code that is supposed to assign a class to only the parent element of the link clicked. This seems to work initially, but then after clicking around a bit, the code seems to get stuck. Here is some sample code of what I'm working with:
<div ng-repeat="item in items track by item.id" class="row" ng-class="{'active': selectItem.this == item.id}">
<a ng-click="selectItem.this = item.id">Move to top</a> {{item.name}}
$scope.selectItem = { this: -1 };
http://plnkr.co/edit/jhahff7OyVTVt615BBp3?p=preview
Any help would be great!
You just need to make the whole text a clickable DOM
<div ng-repeat="item in items track by item.id" class="row" ng-class="{'active': selectItem.this == item.id}">
<a ng-click="selectItem.this = item.id">Move to top <span ng-bind="item.name"></span></a>
</div>
I replaced the a tag with p tag and bind an click event to the p tag. With this refactoring, I don't see any lagging or weird behaviour.
<body ng-controller="MainCtrl">
<div ng-repeat="item in items track by item.id" class="row"
ng-class="{'active': selectItem.this == item.id}">
<p style="cursor: pointer;" ng-click=selectedItem()>
Move to top {{item.name}}
</p>
</div>
</body>
In controller
$scope.selectItem = {};
$scope.selectedItem = function () {
$scope.selectItem.this = this.item.id;
};
Let me know if you still see any issues.
Related
I'm trying to make a nested list of items where user can hide either a certain item or a group of nested items. So far, I'm making use of $indexand I've got this:
<div ng-controller="ItemCtrl">
<div ng-repeat="x in xs" ng-hide="hidden == $index">
<span>{{ x.name }}</span>
<button ng-click="hide($index)">Collapse</button>
<div ng-repeat="y in x.ys" ng-hide="hidden == [x.$index, $index]">
<span>{{ y.name }}</span>
<button ng-click="hide([x.$index, $index])">Collapse</button>
<div ng-repeat="z in y.zs" ng-hide="hidden == [x.$index, y.$index, $index]">
<span>{{ z.name }}</span>
<button ng-click="hide([x.$index, y.$index, $index])">Collapse</button>
</div>
</div>
</div>
</div>
With this controller:
angular.module("app", [])
.controller("ItemCtrl", function($scope) {
$scope.xs = [...]; // My data here
$scope.hidden = -1; // Nothing hidden yet
$scope.hide = function(item) {
$scope.hidden = item;
};
});
It does work. The downside is, there will be too many $index to mantain while the nested list is going deeper. Plus, I have to write all the conditional on every nest level.
My question is, is there any alternative which is simpler, more reliable, and if possible, will generate automatically no matter how many nested item that I have?
please check ui-tree, I think it's what you looking for.
github ui-tree
and the demo
demo
I am displaying the ng-repeat content in two columns.
Using this code works fine:
<div class=storerow ng-repeat="store in stores track by $index" ng-if="$index%2==0">
<div ng-repeat="i in [$index,$index+1]" ng-if="stores[i]!=null" class="ngrepeatstore">
<div class="image-container" style="background-image: url({{stores[i].image}})" ng-click="tileClicked({{stores[i].id}})">
</div>
</div>
However, when I add a filter- it breaks the NG repeat and no content appears:
<div class=storerow ng-repeat="store in stores track by $index" ng-if="$index%2==0">
<div ng-repeat="i in [$index,$index+1] | filter: greaterThan('order', 0) | orderBy:'order'" ng-if="stores[i]!=null" class="ngrepeatstore">
<div class="image-container" style="background-image: url({{stores[i].image}})" ng-click="tileClicked({{stores[i].id}})">
</div>
</div>
the .js for greaterThan
$scope.greaterThan = function(prop, val){
return function(item){
return item[prop] > val;
}}
I tried adding the filter to the first ng-repeat- however that doesn't work as it just applies the filter to the overall content (ie if just one item is greatThan 0, it shows all items- not just the ones greater than 0).
This is because you're actually telling Angular to filter the property order on [$index, $index + 1], an array of two integers, which makes no sense.
I.E. With your delegate comparing index.prop > val, what you're really doing is comparing index['order'] > someValue.
This Plunker demonstrates: http://plnkr.co/edit/FkSrmZuuK4B1ToGNgAnq?p=preview You need to move filter:greaterThan(prop, val) up to the parent ng-repeat. Only there will your filter work.
<div ng-repeat="store in stores | filter:greaterThan2('id', 0) | orderBy:'name'" ng-if="$even">
{{store.name}}
<div ng-repeat="i in [$index, $index+1] | orderBy:angular.identity:true" ng-if="stores[i] !== null">
<strong>store.id</strong> {{i}}
</div>
</div>
I have a list of Items with different button with them. Plunker
Quick View:
I want something like if I click on any of the buttons, related text will be copy to the div above. Also if I click on the button again it will removed from the Div.Same for each of the buttons. [I added manually one to show how it may display ]
I am not sure how to do that in Angular. Any help will be my life saver.
<div ng-repeat="item in csTagGrp">
<ul>
<li ng-repeat="value in item.csTags">
<div class="pull-left">
<button type="button" ng-class='{active: value.active && !value.old}' class="btn btn-default btn-xs">{{value.keys}}</button>
<span>=</span>
</div>
<div class="pull-left cs-tag-item-list">
<span>{{value.tags}}</span>
</div>
</li>
</ul>
</div>
The simplest thing would be to use $scope.tags object to store selected tags and add/remove them with the scope method similar to this:
$scope.tags = {};
$scope.toggleTag = function(tag) {
if (!$scope.tags[tag]) {
$scope.tags[tag] = true;
}
else {
delete $scope.tags[tag];
}
};
Demo: http://plnkr.co/edit/FrifyCrl0yP0T8l8XO4K?p=info
You can use ng-click to put in your scope the selected value, and then display this value instead of "Win".
http://plnkr.co/edit/IzwZFtRBfSiEcHGicc9l?p=preview
<div class="myboard">
<span>{{selected.tags}}</span>
</div>
...
<button type="button" ng-click="select(value)">{{value.keys}}</button>
My problem is, I want to disable div. I ma not getting a way to do it.
<div ng-repeat="item in items">
<div ng-click="somefunction()">{{some value}}</div>
</div>
JS:
$scope.items = [1,2,3,4,5];
I want to disable all div having even value.
Divs cannot be disabled by HTML. You can do it by code:
<div ng-click="somefunction(item)">{{some value}}</div>
$scope.somefunction = function(item) {
if( item % 2 === 0 ) {
return;
}
// rest of logic as before
};
You cant disable div. but you can disable link or button like:
<div ng-repeat="item in items">
<a ng-click="somefunction()" ng-disabled="disabledEvenItems(item)">{{some value}}</a>
</div>
Or you can add style base on it:
<div ng-repeat="item in items">
<div ng-click="somefunction()" ng-class="{{'myClass': disabledEvenItems(item)}}">{{some value}}</div>
</div>
</div>
$scope.disabledEvenItems = function(item) {
return item % 2 !== 0
};
To run the function only for odd values you can use $even / $odd helper properties ngRepeat offers:
<div ng-repeat="item in items">
<div ng-click="$even && somefunction()">{{some value}}</div>
</div>
UPD.
Angular way of doing what you are after is to use expression like this:
<div ng-click="item % 2 && somefunction()">{{some value}}</div>
Try this :
remove onclick from div as shown below
<div ng-repeat="item in items" class="divList">
<div>{{some value}}</div>
</div>
use .filter() to find div with even values and detach click handler
$(function(){
$('.divList div').click(somefunction());
$('.divList div').filter(function(){
var value = parseInt($(this).text()) || 0;
return (value % 2 ==0);
}).off('click');
});
Use display:none
<div id="someId" style="display: none;">
visibility: hidden hides the element, but it still takes up space in the layout.
display: none removes the element completely from the document, it doesn't take up any space.
I have a ng-repeat which display a list of divs and when I click on one it shows an aditionnal div for the clicked item.
This is working
<div ng-repeat="item in items">
<div ng-click="showfull = !showfull">
<div>
<h1>{{item.title}}</h1>
<p>{{item.content}}</p>
</div>
</div>
<div ng-show="showfull">
<p>{{item.info}}</p>
</div>
<hr/>
</div>
My items are loaded from a json containing a list of item and each item have a default attribut showfull set to false in this json. This is working, but now I want to hide all others item in the list when an item is clicked. I've tryied something like this :
This is not working
<div ng-repeat="item in items">
<div ng-click="expand(item)">
<div>
<h1>{{item.title}}</h1>
<p>{{item.content}}</p>
</div>
</div>
<div ng-show="showfull">
<p>{{item.info}}</p>
</div>
<hr/>
</div>
and in the controller I've added a function :
$scope.expand = function(e) {
e.showfull = !e.showfull;
//TODO: put here a foreach logic to hide all other items
}
But even without the foreach logic this is not working, the item don't show the additionnal div when clicked. I have two question :
I suppose this is due to item being "passed by copy" in the expand function or some kind of scope isolation issue but can you explain me why in detail ?
SOLVED
How can I hide all the additional div of other items when I click an item and show the additionnal content for this item ? Do I need to do a directive ?
NOT SOLVED
Thanks
I think you're on the right track. You need to set the showfull on the item and then use ng-show or ng-if to hide it, or as Gavin mentioned, use a class.
On ng-click you can call your expand function, where you pass the item, toggle it and set all others to hidden.
Template:
<div ng-repeat="item in items>
<div ng-click="expand(item)">
<div>
<h1>{{item.title}}</h1>
<p>{{item.content}}</p>
</div>
</div>
<div ng-show="item.showfull">
<p>{{item.info}}</p>
</div>
<hr/>
</div>
Controller:
$scope.expand = function (item) {
angular.forEach($scope.items, function (currentItem) {
currentItem.showfull = currentItem === item && !currentItem.showfull;
});
};
Your expand method is modifying the item, so your ng-show needs to reference the item:
<div ng-show="item.showfull">
<p>{{item.info}}</p>
</div>
To hide all of your items you need to do something like
$scope.expand = function(item) {
angular.forEach(items, function(i) {
if (i === item) {
i.showfull = !i.showfull;
} else {
i.showfull = false;
}
});
};
Shouldn't the second div you want to show be referencing the item?
<div ng-repeat="item in items>
<div ng-click="expand(item)">
<div>
<h1>{{item.title}}</h1>
<p>{{item.content}}</p>
</div>
</div>
<!-- Added item to ng-show -->
<div ng-show="item.showfull">
<p>{{item.info}}</p>
</div>
<hr/>
</div>