I have a list of items which I'm populating using ng-repeat
<ul>
<li ng-repeat="item in items" ng-class="setClass" ng-click="assignClass()">{{item.name}}</li>
</ul>
and in my controller
$scope.assignClass = function(){
$scope.setClass = "sampleClass";
}
When I'm doing like this and clicking on any one item all the items are getting the sampleClass added.
I need this scenario,
When I click on the first item that item should have the sampleClass and when I click on the second item I want both first and second items should have sampleClass
How can I achieve this scenario?
The code you we're using sets the styling for all the list items as you mentioned.
I've change the code a bit to set the class for an individual item in the unordered list.
By calling the assignClass using the selected item as a parameter you can set the class for this item.
<ul>
<li ng-repeat="item in items" ng-class="item.setClass" ng-click="assignClass(item)">
{{item.name}}
</li>
</ul>
$scope.assignClass = function(selectedItem){
selectedItem.setClass = "sampleClass";
}
Pass the item into assignClass function.
<ul>
<li ng-repeat="item in items" ng-click="assignClass(item)">{{item.name}}</li>
</ul>
Then change the class of that item
$scope.assignClass = function(item){
$(item).toggleClass("sampleClass");
}
Related
I have the following HTML markup:-
<ul class="dropdown-menu">
<li ng-repeat="track in songTracks track by $index" ng-class="{active: $index===selectedIndex}">
<a ng-click="setSongTrack(track)">
{{track.name}}
</a>
</li>
</ul>
In Angular, I use this:-
$scope.setSongTrack = setSongTrack;
$scope.selectedIndex = 0;
$scope.index= function(i) {
$scope.selectedIndex=i;
};
Which passes to DASHJS like so:-
function setSongTrack(track) {
musicPlayer.setSongTrack(track);
$scope.selectedIndex = track;
}
musicPlayer being the instance of DASHJS, which parses my audio tracks. This all works - I get a bunch of list elements with the track names, I can click them and independently load each track as expected. However, I need to add some visual way of informing the user which track is currently selected, which is probably best done by way of adding a CSS 'active' class.
Currently this just sets an 'active' class to the first list element, regardless if I click another and it changes the track. If I click another list item, the 'active' class is removed from the first list item. I need the 'active' class to only be on the currently selected track, i.e. the selected list item.
Now I'm stumped. I've read over a lot of similar SO questions and haven't located something which I can get to work.
Can anyone enlighten me? Fairly new to Angular and so, I'm still a bit of a noob with it.
Instead of using the index of the track to mark it as selected, use the track itself. Write a function like trackSelected() which takes a track, and use that to apply a class with ngClass. Eg...
HTML
<ul class="dropdown-menu">
<li ng-repeat="track in songTracks track by $index" ng-class="{ 'active': isSelected(track)} ">
<a ng-click="setSongTrack(track)" ng-bind="track.name">
</a>
</li>
</ul>
JS
$scope.selectedTrack = null;
$scope.setSongTrack = function(track) {
musicPlayer.setSongTrack(track);
$scope.selectedTrack = track;
}
$scope.isSelected = function(track) {
return $scope.selectedTrack === track;
}
This is because you may add or remove tracks from the list in your view at some point, and then the selected index will be invalid.
just go like this:
<ul class="dropdown-menu">
<li ng-repeat="track in songTracks track by $index" ng-class="{active: track===selectedTrack}">
<a ng-click="setSongTrack(track)">
{{track.name}}
</a>
</li>
</ul>
and in your js
$scope.selectedTrack = undefined;
$scope.setSongTrack = function (track) {
musicPlayer.setSongTrack(track);
$scope.selectedTrack = track;
}
This way you can also do stuff like presenting the selected track in your player like below just with one click, no need to fiddle with indexes and such.
<h1>{{selectedTrack.name}}</h1>
<p>
<span>{{selectedTrack.totalTime}}</span>
</p>
Here is a simple fiddle
Alternate Solution
Going the $index way should be like this(Just explaining to help you see what you did wrong)
<ul class="dropdown-menu">
<li ng-repeat="track in songTracks track by $index" ng-class="{active: $index===selectedIndex}">
<a ng-click="setSongTrackIndex($index)">
{{track.name}}
</a>
</li>
</ul>
Notice that i chanced setSongTrack(track) to setSongTrackIndex($index). Then you would of course change your js accordingly, like so:
function setSongTrackIndex(trackIndex) {
musicPlayer.setSongTrack(songTracks[trackIndex]);
$scope.selectedIndex = trackIndex;
}
$scope.setSongTrack = setSongTrack;
$scope.selectedIndex = 0;
If you need further explanation please comment.
Is there a way to get the content of an ordered list item's number?
var list = document.getElementById('list');
list.style.listStyleType = 'upper-roman';
<ol class="list" id="list">
<li class="list__item">apple</li>
<li class="list__item">banana</li>
<li class="list__item" id="target">orange</li>
<li class="list__item">pear</li>
</ol>
That will produce a list of items like this.
I. apple
II. banana
III. orange
IV. pear
Is there a way to get the III string of text of the #target list item?
EDIT:
Roman characters here are just an example. I'd like the ability to access to the content provided by any of the list-style-type options.
The only way I can think of doing this is the following:
1) Get the index of the item (e.g. 3)
2) Have a function like this: https://stackoverflow.com/a/9083076/1324321
3) Run the index through the function
I created a jsfiddle here which can display the chosen selection to the user. Although javascript is not holding this as a string, I first find the index of the selected list item, then I recreate a list of that one item with the "start" attribute being set to that index.
Here is the HTML:
<ol>
<li>first</li>
<li>second</li>
<li id="active">third</li>
<li>Fourth</li>
</ol>
<br/>
<br/>
<div id='selected'>
</div>
And the JQuery:
$(document).ready(function() {
var intt = $('li').index($('#active')) + 1;
$('#selected').html('<ol start="' + intt + '"><li></li></ol>');
});
JSFIDDLE
You could use the start attribute and iterate all list elements.
var list = document.getElementById('list'),
start = list.start || 0;
list.style.listStyleType = 'upper-roman';
Array.prototype.forEach.call(list.getElementsByTagName('li'), function (a, i) {
if (a.id === 'target') {
console.log(i + start);
console.log(a.innerHTML);
}
});
<ol class="list" id="list" start="5">
<li class="list__item">apple</li>
<li class="list__item" >banana</li>
<li class="list__item" id="target">orange</li>
<li class="list__item">pear</li>
</ol>
Im dynamically populating a UL list. This could contain 1 up to 5 items
I want to be able to show the first list item, and then on a click of a button in that list item hide it and show the next.
I have this so far -
HTML Structure
<ul class="grid">
<li class="object">
List Item 1
<a class="show-next">Show the next list item</a>
<li>
</ul>
Javascript
$('.grid .object').hide().filter(':lt(1)').show();
$('.show-next').click(function(){
$(".grid").find(".object").hide().next().show();
});
This code unfortunately is showing all the list items in the UL instead of just the next one.
Anyone give me a hand?
Thanks
Try adding
.removeClass(active);
You could change your code so that you add an active class to the active element, because right now $(".grid").find(".object") is finding all the li objects in your ul, hiding them, looking for the next sibling for every element, and then showing those elements ... that's going to show every element in the list. With an active class added to the currently active button, that would prevent your query from finding all the li elements in the ul.
So for instance:
$('.show-next').click(function(ev){
$(".grid").find(".object.active").hide().next().show().addClass("active");
$(this).parent().removeClass("active");
});
The closing tag for your li is missing the backslash, e.g. </li> instead of <li>.
Apart from that, try this:
$('.grid .object').hide().filter(':lt(1)').show();
$('.show-next').click(function(){
$(".grid").find(".object").hide();
$(this).parent().next().show();
return false;
});
I have put together an example fiddle here: https://jsfiddle.net/utvgLqp6/
Please note that there's no sanity checking to see if it's the last item in the list or not.
Also, if you want to use this on dynamically created elements, you will need to do
$(document).on('click', '.show-next', function() {
instead
First of all your are not closing each list item with </li>. You can take help of parent() to find the parent of the clicked element & then, can hide it & can show the next list item using next()
$('.grid .object').hide().filter(':lt(1)').show();
$('.show-next').click(function(){
$(this).parent().hide().next().show();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="grid">
<li class="object">
List Item 1
<a class="show-next">Show the next list item</a>
</li>
<li class="object">
List Item 2
<a class="show-next">Show the next list item</a>
</li>
<li class="object">
List Item 3
<a class="show-next">Show the next list item</a>
</li>
<li class="object">
List Item 4
<a class="show-next">Show the next list item</a>
</li>
<li class="object">
List Item 5
<a class="show-next">Show the next list item</a>
</li>
</ul>
How's this: https://jsfiddle.net/fznk3ube/2/ I have updated the code and I believe it now includes all the functionality you asked for.
$(document).ready(function () {
$('.object').hide();
var clickListArray = $('.object').toArray();
$(clickListArray[0]).show();
$('.show-next').on("click", function () {
var thisParent = $(this).parent();
var nextInList = $(thisParent).next();
$(thisParent).hide();
$(nextInList).show();
});
});
Below is the code.
<ul class="grid">
<li class="object">
List Item 1<a class="show-next"> Show the next list item</a>
</li>
<li class="object">
List Item 2
<a class="show-next">Show the next list item</a>
</li>
<li class="object">
List Item 3
<a class="show-next">Show the next list item</a>
</li>
</ul>
Below is the script you should insert.
$('.grid .object').hide().filter(':lt(1)').show();
$('.show-next').click(function(){
$eL = $('.grid .object').filter(":visible");
// $(".grid").find(".object").hide().next().show();
if($eL.next().length>0){
$eL.next().show();
}else{
$('.grid .object')[0].show();
}
});
Fiddle
I have a list which I am populating through ng-repeat and in that list I have a nested list with a button on each . Now upon clicking that ul i want to load list from server which can be dynamic. Currently it is overiding the field. Here is my code.
<ul class="qtree">
<li ng-repeat="Childgroup in childGroups">
<span class="glyphicon glyphicon-remove del-btn-tree" data-ng-click="deleteChildGroup(Childgroup.id)" ></span>
<label for="test1">{{Childgroup.name}}</label>
<input type="checkbox" id="{{Childgroup.id}}" data-ng-click="getEntities(Childgroup.id)" />
<ul>
<li ng-repeat="entity in entites">
{{entity.name}}
</li>
</ul>
</li>
</ul>
JavaScript:
$scope.getEntities = function(groupID) {
$scope.entites = [];
var entitiesGroup = ManageGroupsFactory.getEntitiesForGroup(groupID);
entitiesGroup.success(function(entitiesGroup) {
if(entitiesGroup != "") {
for(var i=0; i<entitiesGroup.length;i++) {
$scope.entites.push(entitiesGroup[0]);
}
}
});
entitiesGroup.error(function(data,status){
// TODO for errors
});
The first list populates fine through ng-repeat. Now what I want is upon clicking the checkbox it load's it's specific entities from server and populates in it and every checkbox will have different entites inside it.
Any ideas ?
One technique that has a good chance of working is to generate unique id's for each of the elements in the sub lists. You should be able to combine the parent list name + some value of the inner loop to generate a unique id, eg:
<li ng-repeat="entity in entites track by $id(Childgroup.id + entity.name)">
{{entity.name}}
</li>
Let me know how that works for you.
I have two lists which are sortable and then a button. The user adds items from the first list to the second list and then when they click the button I have some script collect the list item id's from the second list. This part works as intended.
My problem comes when the user accidentally adds an item to the second list that they want to remove. I have a trash can icon that works to removes the item from the list, but then when you hit the button to get the array, it still includes the deleted list item in the array. How do I avoid this? Should I be building the array as the items are added and removed, or is it OK to only build it once after they are done moving list items around like I have done here?
Thanks for taking a look!
http://jsfiddle.net/vYu5k/
<div class="avail_segments_wrap">
<ul id="available" class="segments_available">Available Segments
<li id="1"><span class="title">Item 1</span></li>
<li id="2"><span class="title">Item 2</span></li>
<li id="3"><span class="title">Item 3</span></li>
<li id="4"><span class="title">Item 4</span></li>
<li id="5"><span class="title">Item 5</span></li>
<li id="6"><span class="title">Item 6</span></li>
</ul>
</div>
<br>
<div class="chosen_segments_wrap">
<ul id="chosen" class="segments_chosen">Chosen Segments
</ul>
</div>
<button type="button" id="button1">Button1</button>
jquery:
//make lists sortable
$("#available").sortable({
connectWith: "#chosen"
});
$("#chosen").sortable({
connectWith: "#available"
});
//make add and trash icons functional
$('.ui-icon-add, .ui-icon-delete').on('click', function() {
item = $(this).parent();
item.fadeOut(function() {
if (item.parent().attr('id') == 'chosen') {
$('#available').remove(item.fadeIn());
} else {
$('#chosen').append(item.fadeIn());
}
});
});
//hit button to collect all li id's from ul "chosen".
$("#button1").click( function()
{
var chosenArray = [];
$('#chosen li').each(function(){
chosenArray.push($(this).attr('id'));
});
alert(chosenArray)
}
);
Fiddle Demo
$("#button1").click(function () {
var chosenArray = [];
$('#chosen li:visible').each(function () {
You are hiding the li on delete. But when you create array you are taking all li elements
you need to select only visible elements $('#chosen li:visible').
Read :visible