AngularJS - ng-repeat print me (user_id) first, then order by - angularjs

I need to loop trough object of users but I want to place a concrete user (me) at the beginning.
Example
this.users = [
{
id: 1,
name: "Jane"
},
{
id: 2,
name: "John"
},
{
id: 3,
name: "Me"
},
{
id: 4,
name: "Mark"
}
];
<div ng-repeat="user in ctrl.users">
<!-- SOME OTHER TAGS -->
</div>
And I want it to be this
<div>
<!-- ME -->
</div>
<div>
<!-- JANE -->
</div>
<div>
<!-- JOHN -->
</div>
<div>
<!-- MARK -->
</div>
Is it posible to do it using orderBy or do I have to reorganize my array of users ?

You can use a custom function to do the sorting, see this fiddle
$scope.sortUsers = function (user) {
if (user.name === 'Me') {
// return blank so it's always first in the order
// you can also do 'return 0'; if the sorting is by ID.
return '';
}
// return user.id; if by sorting is by ID
return user.name;
};
Use this in the view
<div ng-repeat="user in users | orderBy: sortUsers">
{{user.name}}<br/>
</div>
For more information, you can also look at this thread and the docs.

Related

Display a value from an object based on an id in AngularJS

I'm currently using a custom filter to display a name when a user id is displayed. So selected_user might be 5, so it then displays "bob" instead of "5":
{{ selected_user | display_name:users }}
The users object contains the entire users table.
The code:
angular.module('myApp', []);
function xCtrl($scope) {
$scope.users = [
{"id":1, "name":"joe"},
{"id":5, "name":"bob"},
{"id":10, "name":"charlie"},
];
$scope.select_user = function(user) {
$scope.selected_user = user;
}
}
angular.module('myApp').filter("display_name", function () {
return function (user_id, users) {
if(user_id) {
return(users[users.map(function(x) { return x.id; }).indexOf(user_id)].name);
}
}
});
This works fine, but it feels like I am doing this inefficiently by passing the entire users object to the filter each time a name is displayed. Is there a better way to do this with filters or are filters the wrong approach?
Demo: http://jsfiddle.net/h2rn3qnw/
One approach is to have the ng-click directive return the $index:
<div ng-repeat="user_data in users"
ng-click="select($index)" class="selection">
{{ user_data.id }} - {{ user_data.name }} - {{$index}}
</div>
$scope.select = function(index) {
$scope.selection = index;
};
Selected User ID: {{ users[selection].id }}<br>
Selected User Name: {{ users[selection].name }}
The DEMO
angular.module('myApp', [])
.controller("xCtrl", function xCtrl($scope) {
$scope.users = [
{"id":1, "name":"joe"},
{"id":5, "name":"bob"},
{"id":10, "name":"charlie"},
];
$scope.select = function(index) {
$scope.selection = index;
};
})
.selection { color:blue; cursor:pointer; }
<script src="//unpkg.com/angular/angular.js"></script>
<div ng-app='myApp'>
<div ng-controller="xCtrl">
Users:<br>
<div ng-repeat="user_data in users"
ng-click="select($index)" class="selection">
{{ user_data.id }} - {{ user_data.name }} - {{$index}}
</div> <!-- ng-repeat -->
<hr>
Selected User ID: {{ users[selection].id }}<br>
Selected User Name: {{ users[selection].name }}
</div> <!-- ng-controller -->
</div> <!-- ng-app -->

Toggle visibility in angular

I’m trying to toggle the visibility of a div in angular
This is my view:
<div ng-repeat="item in data | orderBy:'address' | groupBy:'address'" >
<h5 onclick="toggle_visibility('item1');">{{item.address}}</h5>
<div id="item1">
<ul>
<li>First Name: {{item.firstname}} </li>
</ul>
</div>
In controller:
$scope.data = [
{
firstname: "user",
address: “address1”
},
{
firstname: "user1",
address: “address2”
},
{
firstname: "user2",
address: “address1”
}
];
The issue is when I click on any address header it hides or shows the first name within the first header and it should be when I click on the address header it shows or hides the first name within that address header that I clicked on it. How can I fix this?
Html
<div ng-repeat="item in data | orderBy:'address' | groupBy:'address'" >
<h5 ng-click="toggle_visibility(item);">{{item.address}}</h5>
<div ng-hide="item.invisible">
<ul>
<li>First Name: {{item.firstname}} </li>
</ul>
</div>
JS
$scope.toggle_visibility = function(item) {
item.invisible = !item.invisible
}
add additional boolean property to array and assign that property to ng-hide. then inside click function change the boolean value of that property.
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.data = [
{
firstname: "user",
address: "address1",
hideAddress : false
},
{
firstname: "user1",
address: "address2",
hideAddress : false
},
{
firstname: "user2",
address: "address3",
hideAddress : false
}
];
$scope.toggle_visibility = function(item){
item.hideAddress = !item.hideAddress;
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div ng-repeat="item in data | orderBy:'address' " >
<h5 ng-click="toggle_visibility(item);">{{item.address}}</h5>
<div ng-hide="item.hideAddress">
<ul>
<li>First Name: {{item.firstname}} </li>
</ul>
</div>
</div>
</div>

Compare two lists in angularJs

I have two list that creat from two different json object:
<ul ng-repeat="a in user.data">
<li>
<md-checkbox>
{{ a.name }}
</md-checkbox>
</li>
</ul>
and :
<ul ng-repeat="x in job.data">
<li>
<md-checkbox>
{{ x.user.name }}
</md-checkbox>
</li>
</ul>
I have to compare two lists and remove {{ a.name }} that the same as {{ job.user.name }} . Comparing json objects that have different structure is hard. How can I compare this two list and remove repeated items?
You can use the filter filter ;) using a function instead of a string in the expression argument. Remember this is the syntax of filter
{{ filter_expression | filter : expression : comparator}}
The expression can be a string, an object or a function. Something like this will do
$scope.filterUnemployed = function(value) {
var jobs = $scope.job.data;
for (var i = 0; i < jobs.length; i++) {
// Search every object in the job.data array for a match.
// If found return false to remove this object from the results
if (jobs[i].user.name === value.name) {
return false;
}
}
// Otherwise return true to include it
return true;
}
And then apply the filter to your ng-repeat directive like this
<ul ng-repeat="a in user.data | filter:filterUnemployed">
<li>
<md-checkbox>
{{ a.name }}
</md-checkbox>
</li>
</ul>
Note that this will not modify your original collection but will result in a new copy beign displayed in your html since this is usually the desired effect.
Check the sample for a working demo
angular.module('app', [])
.controller('SampleCtrl', function($scope) {
$scope.user = {
data: [{
name: 'John'
}, {
name: 'Mary'
}, {
name: 'Peter'
}, {
name: 'Jack'
}, {
name: 'Richard'
}, {
name: 'Elizabeth'
}]
};
$scope.job = {
data: [{
jobTitle: 'CEO',
user: {
name: 'John'
}
}, {
jobTitle: 'CFO',
user: {
name: 'Mary'
}
}, {
jobTitle: 'Analist',
user: {
name: 'Jack'
}
}]
};
$scope.filterUnemployed = function(value) {
var jobs = $scope.job.data;
for (var i = 0; i < jobs.length; i++) {
if (jobs[i].user.name === value.name) {
return false;
}
}
return true;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="SampleCtrl">
<h1>All Users</h1>
<ul ng-repeat="a in user.data">
<li>
<md-checkbox>
{{ a.name }}
</md-checkbox>
</li>
</ul>
<h1>Unemployed users</h1>
<ul ng-repeat="a in user.data | filter:filterUnemployed">
<li>
<md-checkbox>
{{ a.name }}
</md-checkbox>
</li>
</ul>
<h1>Employed</h1>
<ul ng-repeat="x in job.data">
<li>
<md-checkbox>
{{ x.user.name }}
</md-checkbox>
</li>
</ul>
</div>
You can create a new array made from filtering one of your arrays :
var newArray = job.data.filter(function(jobData) {
return user.data.some(function(userData) {
return userData.name === jobData.user.name;
});
});
Something like this should help :
for(i=0; i<user.data.length;i++){
for(j=0; j<job.data.length;j++){
if(user.data[i].name === job.data[j].name){
user.date.splice(i,1);
}
}
}
I would appreciate some feedback, at least to know that my code helped you
You can use vanilla javascript, jQuery or library undescore.
Please check related links:
How can I merge two complex JSON objects with only unique or different values only showing in resultant array
How to merge two object values by keys
How to merge two arrays of JSON objects - removing duplicates and preserving order in Javascript/jQuery?
Merging two json objects in Java script?

Dependant ng-repeat in AngularJS

I have a following data structure coming from REST:
scope.taglist =
[ { name: "mylist", tags: ["tag1", "tag2", "tag3", ...]}, { name:
"mylist2", tags: ["tag2.1", "tag2.2", "tag2.3", ...]} ]
In order to present the names of the objects I have the following html:
<div>
<select ng-model="tagNameSelection">
<option ng-repeat="tagObj in taglist" value="{{tagObj}}">{{tagObj.name}}</option>
</select>
</div>
<div class="tagdetails">
<!-- present the list of tags from tagNameSelection -->
</div>
Now I am a little bit of a loss on how to present the tags list of
individual object. I am able to present the array in raw format (by
sticking {{tagNameSelection}} inside the tagdetails div) but when I
try to iterate through those with ng-repeat angular gives a error
message.
Oddly enough when I hard-code one of the tag lists to the scope in controller the ng-repeat works flawlessly.
Maybe you interesting something like this:
HTML
<div ng-controller="fessCntrl">
<div>
<select ng-model="tagNameSelection"
ng-options="tagObj as tagObj.name for tagObj in taglist"
ng-change="change(tagNameSelection)"></select>
</div>
<pre>{{tagNameSelection.tags|json}}</pre>
<div class="tagdetails">
<ul ng-repeat="tag in tagNameSelection.tags">
<li>{{tag}}</li>
</ul>
</div>
</div>
Controller
var fessmodule = angular.module('myModule', []);
fessmodule.controller('fessCntrl', function ($scope) {
$scope.change = function (value) {
};
$scope.taglist = [{
name: "mylist",
tags: ["tag1", "tag2", "tag3"]
}, {
name: "mylist2",
tags: ["tag2.1", "tag2.2", "tag2.3"]
}]
});
fessmodule.$inject = ['$scope'];
See Fiddle

AngularJS : Checkbox Label retain original value on un-check

Please look at http://jsfiddle.net/mahbub/sbNty/4/
<div ng-app="">
<div ng-controller="Ctrl">
<ul>
<li ng:repeat="status in statuses"><label><input type="checkbox" data-ng-model="status.type" data-ng-true-value="closed" data-ng-false-value="{{status.type}}" />{{status.type}}</label></li>
</ul>
</div>
</div>​
As you can see the label of the checkboxes are printed based on the status type from the JSON. Now on unchecking, the label becomes false. I must be missing some correct way to get back to the originial label text upon unchecking the checkbox.
I mean when I uncheck, the label needs to be "open" or whatever it was initially.
Any help is greatly appreciated.
Thanks
Finally i did it using ngInit and setting a different variable within the scope object. See the demonstration here http://jsfiddle.net/mahbub/sbNty/5/
<div ng-app="">
<div ng-controller="Ctrl">
<ul>
<li ng:repeat="status in statuses"><label><input ng-init="status.oldStat=status.type" type="checkbox" ng-model="value" ng-click="selectV(value,this)">{{status.type}}</label></li>
</ul>
</div>
</div>​
Controller :
'use strict';
function Ctrl($scope) {
$scope.statuses = [{
id: 1,
type: 'open'},
{
id: 2,
type: 'open'},
{
id: 3,
type: 'new'},
{
id: 4,
type: 'closed'},
{
id: 5,
type: 'open'},
{
id: 6,
type: 'new'},
{
id: 7,
type: 'open'}
];
$scope.selectV = function(val, stat) {
if (val) {
stat.status.type = "closed";
} else {
stat.status.type = stat.status.oldStat;
}
}
}​

Resources