Update part of page on click with angularjs - javascript

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>

Related

How to filter ng-repeat list on empty string values?

How can I filter an ng-repeat to show all items where a certain columnfield is an empty string? When I try this it always seem to give the full list. I only want to see the person with id 1.
Fiddlejs example
Controller:
var people = [{
name: '',
age: 32,
id: 1
}, {
name: 'Jonny',
age: 34,
id: 2
}, {
name: 'Blake',
age: 28,
id: 3
}, {
name: 'David',
age: 35,
id: 4
}];
$scope.filteredPeople = $filter('filter')(people, {
name: ''
});
$scope.people = people.slice(0);
View:
<li ng-repeat="p in filteredPeople">
<h4>{{p.name}} ({{p.age}}) id: {{p.id}}</h4>
</li>
You can use Angular's 'filter' in 'ng-repeat':
// In template:
<li ng-repeat="p in filteredPeople | filter : filterPeople">
<h4>{{p.name}} ({{p.age}}) id: {{p.id}}</h4>
</li>
// In controller:
$scope.filterPeople = function(item) {
return !item.name;
};
To list users that have name:
<li ng-repeat="p in filteredPeople" ng-if="p.name !== ''">
<h4>{{p.name}} ({{p.age}}) id: {{p.id}}</h4>
</li>
To list only users that do not have name:
<li ng-repeat="p in filteredPeople" ng-if="p.name === ''">
<h4>{{p.name}} ({{p.age}}) id: {{p.id}}</h4>
</li>
Just pass third parameter to filter saying true which will perform strict check
$scope.filteredPeople = $filter('filter')(people, {
name: ''
}, true);
Forked JSFiddle

How do i implement a sliding filter on ng-repeat in angularjs

I am trying to implement a simple sliding filter in angular, but my ng-repeat does not seeem to be responding
The fiddle for this is here http://jsfiddle.net/zn4b89n0/1/
I have tried the following
HTML
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.4/ui-bootstrap-tpls.min.js"></script>
<script src="https://rawgit.com/rzajac/angularjs-slider/master/dist/rzslider.js"></script>
<div ng-app="myapp">
<div ng-controller="TestController as vm">
<p>Price 1: {{vm.priceSlider1.value}}</p>
<rzslider rz-slider-model="vm.priceSlider1.value" rz-slider-floor="vm.priceSlider1.floor" rz-slider-ceil="vm.priceSlider1.ceil"></rzslider>
<ul ng-repeat="friend in vm.friends ">
<li>{{friend.name | filter:filterFn}}</li>
</ul>
</div>
</div>
JS
var myApp = angular.module('myapp', ['rzModule', 'ui.bootstrap']);
myApp.controller('TestController', TestController);
function TestController($scope, $timeout) {
var vm = this;
vm.priceSlider1 = {
floor: 80,
ceil: 100,
value: 85
};
vm.friends = [
{ name: "Peter", age: 20 },
{ name: "Pablo", age: 55 },
{ name: "Linda", age: 20 },
{ name: "Marta", age: 37 },
{ name: "Othello", age: 20 },
{ name: "Markus", age: 32 }
];
vm.filterFn = function(friend)
{
// Do some tests
if(friend.age >= vm.priceSlider1.value )
{
return true; // this will be listed in the results
}
return false; // otherwise it won't be within the results
};
vm.refreshSlider = function () {
$timeout(function () {
$scope.$broadcast('rzSliderForceRender');
});
};
}
How do i get this to work, thank you for any and all assistance
You should use your filter in ng-repeat and execute the filter:
<ul ng-repeat="friend in vm.friends | filter: vm.filterFn() ">
<li>{{friend.name}}</li>
</ul>
You can simplify the filter function:
vm.filterFn = function()
{
return function(item){
//return the whether age attribute of each item (friend) is greater than your value
return item['age'] >= vm.priceSlider1.value;
}
};
Here you can try the updated fiddle: http://jsfiddle.net/Ln9cgrve/
I hope that solves your problem...
Looks like the problem in ngRepeat part. It should be
<ul ng-repeat="friend in vm.friends | filter:vm.filterFn">
<li>{{friend.name}}</li>
</ul>
Note, filter is in ngRepeat directive and also filter function should be referred as vm.filterFn.

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).

ng-repeat continuously fired on hover

I'm using UI-Select 0.8.4 and have a large data set. Then I'm using UI-Select to display property values in a dropdown beside the data set. I'm using that for filters. So when choosing from the dropdown, will filter the results.
Every time when I hover over some item in the dropdown, it always fires the ng-repeat filter.
This is lagging my application because I'm working with a large set in the ng-repeat.
Why is this?
GIF:
http://i.imgur.com/cStlXzy.gif
Plunker (open console and see for yourself):
http://plnkr.co/edit/OxiutZ8t4IX1bOxiOTgo?p=preview
HTML:
<h3>Age list</h3>
<p>Selected: {{age.selected}}</p>
<ui-select ng-model="age.selected" ng-disabled="disabled" style="width: 300px;">
<ui-select-match placeholder="Select a person">{{$select.selected}}</ui-select-match>
<ui-select-choices repeat="age in ageArray | filter: $select.search">
<div ng-bind="age | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
JavaScript:
$scope.theFilter = function(item) {
console.log(item);
return item;
};
$scope.ageArray = [];
$scope.$watch('people', function(item) {
for(var i = 0; i < item.length; i++) {
$scope.ageArray.push(item[i].age);
}
});
$scope.people = [
{ name: 'Adam', email: 'adam#email.com', age: 10 },
{ name: 'Amalie', email: 'amalie#email.com', age: 12 },
{ name: 'Wladimir', email: 'wladimir#email.com', age: 30 },
{ name: 'Samantha', email: 'samantha#email.com', age: 31 },
{ name: 'Estefanía', email: 'estefanía#email.com', age: 16 },
{ name: 'Natasha', email: 'natasha#email.com', age: 54 },
{ name: 'Nicole', email: 'nicole#email.com', age: 43 },
{ name: 'Adrian', email: 'adrian#email.com', age: 21 }
];
Edit: I even tried to filter the property values out of the "data set array" and using that in the dropdown, but it doesn't work.
Edit 2: If you think that the watch was triggering this, I removed the watch and this is still a problem: http://plnkr.co/edit/oD3Tt3vfjtOjADMnemW1?p=preview
Edit 3: Still haven't found a solution for this so I'm stuck with chosen. I created an issue but haven't gotten any response. Please upvote the issue if you want this fixed.
The issue is that the filter is executing on every $digest (every ng-mouseenter, ng-click, etc). For a huge data set, this can obviously kill performance. (See this article http://www.bennadel.com/blog/2489-how-often-do-filters-execute-in-angularjs.htm)
Instead, try a $watch on the age.selected value, then applying a filter only when that value actually changes.
http://plnkr.co/edit/TIeKPAyrAQsGHwakqwEp?p=preview
HTML
<!-- filtered list "ageMatches" -->
<ul ng-show="age.selected">
<li ng-repeat="person in ageMatches">{{person.name}} - {{person.age}}</li>
</ul>
<!-- default list of all "people" -->
<ul ng-hide="age.selected">
<li ng-repeat="person in people">{{person.name}} - {{person.age}}</li>
</ul>
JS
// add age to scope
$scope.age = {};
// add age match placeholder
$scope.ageMatches = [];
// watch age.selected for changes, apply filter
$scope.$watch('age.selected', function(newVal, oldVal){
if(newVal){
$scope.ageMatches = $filter('filter')($scope.people, {age: newVal});
}
});

Set Model to a specific object from array

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/

Categories