populate data in ng-repeat with dynamic variables - javascript

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.

Related

Adding an active state to list item using angular

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.

How to query a data attribute value in javascript (no jquery)?

If I have a grid made up of ul's (the rows) and li's (the cells), I wanted to get a specific cell based on the data attribute values of the ul and the li:
document.querySelectorAll(div.grid ul[data-${this.y}] li[data-${this.x}]'_
When I searched on MDN, I only found how to retrieve the html element based on the data attribute, but not it's value.
Any pointers would be greatly appreciated - also no jQuery please.
You could use the String interpolation and get it worked.
Here is what you could do.
document.addEventListener('DOMContentLoaded', function() {
let ulData = 2,
liData = 4;
document.querySelector(`div.grid ul[data="${ulData}"] li[data="${liData}"]`).classList.add("red");
});
.red {
color: red;
}
<div class="grid">
<ul data="2">
<li data="1">
One
</li>
<li data="2">
Two
</li>
<li data="3">
Three
</li>
<li data="4">
Four
</li>
<li data="5">
Five
</li>
</ul>
</div>

Isolated scope for individual items in list in angularjs

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");
}

How to get li value and print it again

I am creating a website for a university project.
What i have is 3 tables that contain 1 list of links each. The links represent lessons and to what they link it doesn't matter. When a student chooses a lesson then that lesson is supposed to be presented at the bottom of the page without leaving the list.
My code is the following:
<!DOCTYPE HTML>
<html>
<link rel="stylesheet" type="text/css" href="style.css"> <!--Links the page with my style.css file-->
<body>
<head>
<title>Competences</title>
</head>
<?php
$name = $_GET['name'];
$surname = $_GET['surname'];
echo "<h3>Hello " .$name." ".$surname"</h3>" ;
?>
<div class="background">
<h5>Below are various competences organised into three main categories. Select the ones you think are more important for your studies by clicking on them.</h5>
<div class="box" style="inline" id="1">
<h2>INSTRUMENTAL</h2>
<ul>
<h4>
<li onClick="Copy()">Capacity for analysis and synthesis</li>
<li onClick="Copy()">Capacity for organisation and planning</li>
<li onClick="Copy()">Basic general knowledge</li>
<li onClick="Copy()">Grounding in basic knowledge of the profession</li>
<li onClick="Copy()">Oral and written communication in your native language</li>
<li onClick="Copy()">Knowledge of a second language</li>
<li onClick="Copy()">Elementary computing skills</li>
<li onClick="Copy()">Information management skills (ability to retrieve and analyse information from different sources)</li>
<li onClick="Copy()">Problem Solving</li>
<li onClick="Copy()">Decision-making</li>
</h4>
</ul>
</div>
<div class="box2" style="inline" id="2">
<h2>INTERPERSONAL</h2>
<ul>
<h4>
<li onClick="Copy()">Critical and self-critical abilities</li>
<li onClick="Copy()">Teamwork</li>
<li onClick="Copy()">Interpersonal skills</li>
<li onClick="Copy()">Ability to work in an interdisciplinary team</li>
<li onClick="Copy()">Ability to communicate with experts in other fields</li>
<li onClick="Copy()">Appreciation of diversity and multiculturality</li>
<li onClick="Copy()">Ability to work in an international context</li>
<li onClick="Copy()">Ethical commitment</li>
</h4>
</ul>
</div>
<div class="box3" style="inline" id="3">
<h2>SYSTEMIC</h2>
<ul>
<h4>
<li onClick="Copy()">Capacity of applying knowledge in practice</li>
<li onclick="Copy()">Research Skills</li>
<li onClick="Copy()">Capacity to learn</li>
<li onClick="Copy()">Capacity to adapt to new situations</li>
<li onClick="Copy()">Capacity for generating new ideas(creativity)</li>
<li onClick="Copy()">Leadership</li>
<li onClick="Copy()">Understanding of cultures and customs of other countries</li>
<li onClick="Copy()">Ability to work autonomously</li>
<li onClick="Copy()">Project design and management</li>
<li onClick="Copy()">Initiative and entrepreneurial spirit</li>
<li onClick="Copy()">Concern for quality</li>
<li onClick="Copy()">Will to succeed</li>
</h4>
</ul>
</div>
</div>
<form action="step3.php" method="get">
<input type="submit" value="Submit Choices"/>
</form>
<h5>You have selected the following competences:</h5>
<script type="text/javascript">
var count = new Array();
var i=0;
var column_id = "id";
var col1=0;
var col2=0;
var col3=0;
function Copy()
{
count[i] = "value";
i++;
var div = document.createElement('div');
div.innerHTML = '<div>' + count[i] + '</div>';
if (column_id==1)
{
col1+=1;
}
else if (column_id==2)
{
col2+=1;
}
else if (column_id==3)
{
col3+=1;
}
div.innerHTML = '<div>'Competences Selected: + col1 + " Instrumental" + col2 + " Interpersonal" + col3 +" Systemic."'</div>';
}
</script>
</body>
</html>
Also in competences Selected I will have to tell to the student the number of subjects he has selected from Instrumental list, Interpersonal list and Systemic List.
lets say for example my list is that :
Instrumental
1.option1
2.option2
if option 1 is selected as the lesson from instumental then i will have something like:
Competences Selected: 1 Instumental,0 Interpersonal, 0 Systemic
1.option1
As you can see i tried doing it with javascript but i am not quite sure how to make it work.. I don't know if value is what i should take into consideration or if i am supposed to do it with javascript.
I am not 100% sure what you are doing here, but there are a few things you may want to look at: -
In the line count(i) = "value"; I assume that you are refering to the array. In which case it should be count[i] = "value"
In the line "<div>count(i)</div>"; I assume that you mean to have the value at the count array index in the div, in which case you want div.innerHTML = '<div>' + count[i] + '</div>';
You have onClick="count()" referencing a count() method but also a global count() array. Change the name of the function to avoid confusion.
You have a javascript function called onclick, to avoid confusion give it a name that describes what the function does rather than using the generic onclick name.
Try to reduce the problem you are having to the smallest subset of self-contained code and you will be more likely to get answers.
Update:
Based on your updated code, I think I can see what you are wanting to do. See here for a cut down example, you should be able to apply the same to the rest of the page.
Some notes: -
calling count[i] = "value" will not get you the value of the <li> element. You need to pass the element and call innerHTML or retrieve it in the html.
You actually want the value of the as far as I can tell, so you might as well put the onclick in the <a>.
calling var column_id = "id"; will not get you the id of the containing div. You need to first get the div by a selector. I suggest you look into using jQuery to achieve this. For brevity, I just passed the value in the javascript call.
I left an alert in the Copy() function so you can see what is passed in, you will want to remove this.

How to save HTML ul-li structure into javascript object

i have this following html structure usilg ul and li.
<ul class="treeview" id="productTree">
<li class="collapsable lastCollapsable">
<div class="hitarea collapsable-hitarea lastCollapsable-hitarea"></div>
<span id="top1" class="">top1</span>
<ul>
<li class="collapsable lastCollapsable">
<span class="">mod1</span>
<ul>
<li class="last">
<span>bottom1</span>
</li>
</ul>
</li>
</ul>
</li>
<li class="collapsable lastCollapsable">
<span id="top2" class="">top2</span>
<ul>
<li class="collapsable lastCollapsable">
<span class="">mid2</span>
<ul>
<li class="last">
<span>bottom2</span>
</li>
</ul>
</li>
</ul>
</li>
</ul>
the website allows user to add more data under this structure and am using jquery treeview to show the tree structure dynamically.
Now i need to save this whole ul-li structure into a js object for future use in the website. how do i achieve this? the last node("bottom1 and bottom2 here") has a class "last" if that helps.
as we can add data dynamically we can be sure how much levels of ul li is there at the end when user clicks "save"
You can use recursive function to save a tree object;
function save(obj_ul, tree){
var obj_lis = obj_ul.find("li")
if (obj_lis.length == 0) return;
obj_lis.each(function(){
var $this = $(this);
if($this.parent("ul").get(0) == obj_ul.get(0))
{
tree.push({
name : $this.find('> span').text(),
child : save($this.find("ul").first(), [])
});
}
});
return tree;
}
console.log(save($('#productTree'), []));
If you want to reprouce the same thing verbatim, as a string of HTML elsewhere on the site, you could just do this? Then .append() or .prepend() treeview where you like.
​var treeview = $('#productTree').parent().html()
Assuming you want JSON:
function save(){
var tmp = [];
$('#productTree li.collapsable').each(function(){
var $this = $(this),
$spans = $this.find('span'),
o = [];
$spans.each(function(){
o.push($(this).text())
})
tmp.push(o);
});
return tmp;
}
You could also use map() to accomplish the same thing, too.
EDIT: Updated, assuming your text will live inside a span. This will create an array of arrays, each containing the text from the spans inside each of your list-items.

Categories