Set Model to a specific object from array - javascript

I am trying to set the model of a DOM element to a specific child object given a specific attribute. in this specific example, the "Employees" object is structured in this fashion:
var Employees = [
{EmployeeID:1000
Name: Jimmy
ManagerID: null}
{EmployeeID:1001
Name: James
ManagerID: 1000}
{EmployeeID:1002
Name: Steve
ManagerID: 1000}
]
I was hoping that an inline Curley Brace Directive using a filter would be able to help me out with it. What follows obviously doesn't work, but hopefully it demonstrates what I would like it to do.
<div ng-repeat="Emp in Employees">
<span>Employee #:{{Emp.EmployeeID}}</span>
<img src="../../Content/images/Photos/{{Emp.EmployeeID}}.jpg"/>
<h4>{{Emp.Name}}</h4>
<h5>Manager:</h5>
<!--The following is what I do not know how to do-->
<span>{{Employees.Name | filter:Employees.EmployeeID = Emp.EmployeeID }}</span>
</div>
With the End Result being:
Employee #:1000
<img>
Jimmy
Manager:
<!--I'll figure out what to do with null values in a bit. first things first-->
Employee #:1001
<img>
James
Manager:
Jimmy
Employee #:1002
<img>
Steve
Manager:
Jimmy

The JS
angular.module("myApp", []).controller("MyCtrl", function($scope){
$scope.employees = [
{EmployeeID:1000,
Name: 'Jimmy',
ManagerID: null},
{EmployeeID:1001,
Name: 'James',
ManagerID: 1000},
{EmployeeID:1002,
Name: 'Steve',
ManagerID: 1000}
]
$scope.findManager = function(empId) {
console.log('here');
//debugger;
for(var i=0; i<$scope.employees.length; i++)
{
var curEmployee = $scope.employees[i];
console.log(curEmployee.EmployeeID)
if(curEmployee.EmployeeID == empId)
return curEmployee.Name;
}
return "";
}
});
The HTML
<div ng-app="myApp" ng-controller="MyCtrl">
<div ng-repeat="Emp in employees">
<span>Employee #:{{Emp.EmployeeID}}</span>
<img ng-src="../../Content/images/Photos/{{Emp.EmployeeID}}.jpg"/>
<h4>{{Emp.Name}}</h4>
<h5>Manager:</h5>
<!--The following is what I do not know how to do-->
<span>{{findManager(Emp.ManagerID)}}</span>
</div>
</div>
The fiddle
http://jsfiddle.net/EhJLu/

Related

Learning Handlebars: why isn't data being passed to my template if I don't use `this`

I'm learning Handlebars and using this piece of code below after looking at a couple of tutorials. Below, my code won't work if I don't use the keyword this; I tried {{#each shoesData}} and nothing happens to my HTML. If I don't want to use this, it will work only if I change the shoesData to JS Example #2 (following an example from another tutorial that uses the name of an object and not this keyword) and also, in my template wrote {{#each shoes}}. What's the difference?
<h3>The List of Shoes:</h3>
<ul class="shoesNav"></ul>​
<script id="shoe-template" type="text/x-handlebars-template">
{{#each this}}
<li class="shoes">{{name}} -- Price: {{price}}</li>
{{/each}}
</script>
JavaScript #1
var shoesNav = document.getElementsByClassName("shoesNav");
var theTemplateScript = document.getElementById("shoe-template").innerHTML;
var theTemplate = Handlebars.compile(theTemplateScript);
var shoesData =[
{
name: "Nike",
price: 199.00
},
{
name: "Loafers",
price: 59.00
},
{
name: "Wing Tip",
price: 259.00
}
];
var theCompiledTemplate = theTemplate(shoesData);
shoesNav[0].innerHTML = theCompiledTemplate;
JavaScript #2
var shoesData =
{
shoes: [
{
name: "Nike",
price: 199.00
},
{
name: "Loafers",
price: 59.00
},
{
name: "Wing Tip",
price: 259.00
}
]
};
The item you are passing to your template is the array that is referenced by the variable 'shoesData'. So when the template sees it the 'this' object looks like this:
[
{
name: "Nike",
price: 199.00
},
{
name: "Loafers",
price: 59.00
},
{
name: "Wing Tip",
price: 259.00
}
]
In Javascript #2, the object passed to the template is the value referenced by shoesData, which in this case is:
{
shoes: [
{
name: "Nike",
price: 199.00
},
{
name: "Loafers",
price: 59.00
},
{
name: "Wing Tip",
price: 259.00
}
]
};
Do you see the difference? In the second example, the template sees an object with a property of shoes. In your example (Javascript #1) it simply sees an array.
The this parameter in both cases represents what is passed to the template so in your javascript it works with this because it represents an array that can be iterated over by the {{#each ... }}.
To fix this issue to work the way you expect, change the shoesData to look like this:
shoesData = {
shoes:
[
{
name: "Nike",
price: 199.00
},
{
name: "Loafers",
price: 59.00
},
{
name: "Wing Tip",
price: 259.00
}
]
}
Now you can use {{#each shoes}} in your template.
Another way to think of this, if you are still stuck, is what do you see if you do console.log(shoesData) in both examples? This will tell you what the handlebars will see as the this object, and if you do console.log(shoesData.shoes) in the second example, this is what will be iterated over when you do {{#each shoes}}.

Filtering in angularJS by arrays atributtes

I'm building a web app and I'm using AngularJS for the front-end.
I have a problem when I try to filter some selects.
This is my case:
I have an object called 'Games'. It represents football games.
Games have two atributtes: id as an identifier and Team.
Team is a 'Teams' array. Now I will explain how is each Team.
A team has three attributes: id, name and League, all of them represent a League.
A League has two attributes: id and name.
I want to fill a select with Games and I want to filter this select by League. The problem is that the League is into each Team and when I try to do a filter like this: filter:{Team[0].League.id : 1} it is not working and I don't know why.
I have made an example on fiddle:
<div ng-app="myapp">
<fieldset ng-controller="FirstCtrl">
<select ng-model="newGame" ng-options="game.Team[0].name + ' vs ' + game.Team[1].name for game in Games | filter:{Team[0].League.Name : 'League spain'}"></select>
<select ng-model="teamsNewGame" ng-options="team.name for team in Teams | filter:{}"></select>
</fieldset>
function TodoCtrl($scope) {
$scope.LeagueSpain = { id: 1,
name: 'League spain'};
$scope.LeagueUK = { id: 2,
name: 'League UK'};
$scope.TeamBarcelona = {id:1,
name: 'Barcelona',
League: LeagueSpain};
$scope.TeamMadrid = {id:2,
name:'Madrid',
League: LeagueSpain};
$scope.TeamChelsea = {id:3,
name:'Chelsea',
League: LeagueUK};
$scope.TeamArsenal = {id:4,
name:'Arsenal',
League: LeagueUK};
$scope.Teams = [TeamBarcelona, TeamMadrid, TeamChelsea,
TeamArsenal];
$scope.Games = [{id: 1,
Team:[TeamBarcelona,
TeamMadrid]
},
{id: 2,
Team:[TeamChelsea,
TeamArsenal] }
];
}
http://jsfiddle.net/vqzj37ys/1/
Edit: the second filter is empty because I don't know how to filter teams that are in the game.Team array

How to use controller variables along with ng-click to toggle class?

http://plnkr.co/edit/nEfBE33AJen3mz9YvjeC?p=preview
I have a list of tag buttons, by default after all the items are loaded, I set the first 3 items to have the selected class.
Now I also need tags to gain or lose the selected class on ng-click.
How would you combine the code in the markup or controller?
.controller('PageCtrl',
['$scope',
function($scope) {
var vs = $scope;
vs.message = "1st, 2nd and 3rd item should be selected by default:";
// Gives the 1st 3 items the selected class
vs.toggleTags = { item: [0, 1, 2] };
// the ng-click to individually toggle the selected class:
vs.selectTag = function(term) {
alert(term +' in tag #'+ vs.toggleTags.item);
};
vs.tags = [
{name: 'aaa'},
{name: 'bbb'},
{name: 'ccc'},
{name: 'ddd'},
{name: 'eee'},
{name: 'fff'},
{name: 'ggg'}
];
}]);
HTML
<ul>
<li ng-repeat="(k, m) in tags"
ng-class="{'selected':toggleTags.item.indexOf(k) > -1}"
ng-click="toggleTags.item = $index; selectTag(m.name)">
<div class="tag">{{m.name}}</div>
</li>
</ul>
Basically I'd like to combine something like: {'selected' : toggle.state} into the ng-class line. Right now my code deselects everything.
Any ideas?
If u dont want to change data you get from server - you can create selection model separately:
<li ng-repeat="(k, m) in tags"
ng-class="{'selected':selectedModel[$index]}"
ng-click="selectedModel[$index] = !selectedModel[$index]">
http://plnkr.co/edit/QpoAs9XFknKug8mpNkkO?p=preview
Ofc, better to use ids not indexes, if u have any.
http://plnkr.co/edit/bqXi4GHxJjbD03ilJ4Me?p=preview
New plnkr (for toggling):
http://plnkr.co/edit/bqXi4GHxJjbD03ilJ4Me?p=preview
You can do something like this. Using an extra variable inside your tags
vs.tags = [
{name: 'aaa', active: true},
{name: 'bbb', active: true},
{name: 'ccc', active: true},
{name: 'ddd', active: false},
{name: 'eee', active: false},
{name: 'fff', active: false},
{name: 'ggg', active: false}
];
You can achieve this by updaing your controller function as :
vs.selectTag = function(term,k) {
if(vs.toggleTags.item.indexOf(k) == -1){
vs.toggleTags.item.push(k)
}
else {
vs.toggleTags.item.splice(vs.toggleTags.item.indexOf(k),1);
}
alert(term +' in tag #'+ vs.toggleTags.item);
};
And update html to:
<li ng-repeat="(k, m) in tags"
ng-class="{'selected':toggleTags.item.indexOf(k) > -1}"
ng-click="selectTag(m.name,k)">
<div class="tag">{{m.name}}</div>
</li>
Every button have an object so instead of using another array to check if the button is checked you can add it to the existing object (m object in you code).
That way you can do {'selected': m.state} which is pretty clean.
As maddog showed, you just need to add the active property to the tags object and check there if it's selected and not in a different array, there is no reason for this (at least not one you have shown us).

Handlebars JS (or EJS) templating: Divide list into categories

I want to create an unordered list based on an array of objects using Handlebars JS.
The objects take the following form:
{ name: 'NameOne', id: 001, category: 2 }, { name: 'NameTwo', id: 002, category: 1 }, { name: 'Name Three', id: 003, category: 1 }, { name: 'Name Four', id: 004, category: 3 }...
At the moment I have a template with an each function which compiles an UL with each object making a new list item, as so:
{{#each this}}
<li>{{ name }}</li>
{{/each}}
What I would like to do is find the simplest way to divide the list depending on categories, so I could end up with something like this...
Category 1
NameTwo
NameThree
Category 2
Name One
Category 3
Name Four
If I can do this only with the template, that would be perfect, but I can also change the JS which compiles the template if needed. I would also be open for using EJS templates if that is a better solution. I have thought of a couple of solutions, but all seem very over-complicated and don't work very well, but surely this can be quite a common problem and there must be good solutions.
Many thanks.
Hi when I'm solving problems like this, I tend to manipulate the data though JavaScript to keep the template clean.
How about trying something like this:
HTML
{{#each list}}
<ul>
<li>
Category {{#key}}
<ul>
{{#each this}}
<li>{{name}}</li>
{{/each}}
</ul>
</li>
</ul>
{{/each}}
JS
var rawData = [
{ name: 'NameOne', id: 001, category: 2 },
{ name: 'NameTwo', id: 002, category: 1 },
{ name: 'Name Three', id: 003, category: 1 },
{ name: 'Name Four', id: 004, category: 3 }
];
var data = {
list:{
}
};
for (var i = 0; i < rawData.length ; i++) {
var a = rawData[i];
var cat = a.category;
if(typeof data['list'][cat] === 'undefined'){
data['list'][cat] = [];
}
data['list'][cat].push(a);
}
Also here is a jsfiddle

Update part of page on click with angularjs

I'm new to angular. If this is a duplicate, please post a link.
Ok, so I in javascript I have a list of items, lets say this:
[{
name: 'Bob',
age: 24,
},
{
name: 'Smith',
age: 56,
},
{
name: 'Lisa',
age: 12,
}]
All the name properties are printed out in a list at the left of the page, like this:
<li data-ng-repeat="person in persons">{{tournament.name}}</li>
All this works, but here is the thing.
When I click a person in the list, I want to display more detailed information to the right of the list about that person.
If I click on Bob in the list, it should display both name and age to the right of the list.
I can't figure this out in angular. Can anyone explain how I update a part of the page with that information?
You can do that with a simple click on your li like that :
<ul data-ng-repeat="person in persons">
<li ng-click="detail($index)">{{person.name}}</li>
</ul>
The $index is the index of the ng-repeat really useful to mange with arrays !
You add a div where you want to see the person details :
<div>
{{personDetail.name}} {{personDetail.age}}
</div>
In your controller implement the detail function like that :
var app = angular.module('MyApp', []);
app.controller('MyCtrl', function($scope){
$scope.persons = [{
name: 'Bob',
age: 24,
},
{
name: 'Smith',
age: 56,
},
{
name: 'Lisa',
age: 12,
}];
$scope.detail = function(index){
$scope.personDetail = $scope.persons[index];
};
});
And voila !
working plnkr here : http://plnkr.co/edit/Wg4UD6?p=preview
<!-- left -->
<li data-ng-repeat="person in persons" ng-click="obj.selected=$index">
{{person.name}}
</li>
<!-- right -->
<div>
{{persons[obj.selected]["name"]}}
{{persons[obj.selected]["age"]}}
</div>
Controller:
$scope.obj = {
selected:-1
};
HTML
<li data-ng-repeat="person in persons" ng-click="clicked(person)">
controller
$scope.selectedNode = "";
...
$scope.clicked = function(info) {
$scope.selectedNode = info;
};
now create right side:
<div>
<pre>{{selectedNode | json}}</pre>
</div>

Categories