Hide graphically some items iterating with ng-repeat - javascript

I am developing a web-application using Angular Js.
I want to fill a div, into my html view, using the ng-repeat directive. The array used by ng-repeat has some duplicates, but in my view I want to display item only once (if an element has already been shown, its copies must be graphically hidden). How can I do this?
<div ng-repeat="item in selectedProcedures track by $index">
<span>{{item.id}}</span>
</div>

Just use a unique filter like this:
<div ng-repeat="item in selectedProcedures track by $index | unique : 'id'">
<span>{{item.id}}</span>
</div>
Then create the unique filter:
app.filter('unique', function() {
return function(collection, property) {
var output = [];
angular.forEach(collection, function(item) {
//check if it exists in output on the basis of property, if not then add to output
output.push(item);
})
return output;
}
})
'property' in the function is 'id' in the example whereas collection refers to the entire array.

I would recommend you not to hide generated Html, but to add a filter to delete duplicates :
<div ng-repeat="item in selectedProcedures track by $index | deleteDuplicates">
. . .
</div>
angular.module('myApp').filter('deleteDuplicates', function(){
return function filterCore(source)
{
var out = [];
// . . .
return(out);
};
});
Here is the AngularJS custom filter tutorial.

Related

angular dynamic property name in nested ng-repeat

I'm wondering is there any way to add dynamically generated names in nested ng-repeat, for example:
<div ng-repeat="x in JSONfile">
<div ng-repeat="i in x.name">
<span><a ng-href="{{i.link}}">{{i.name}}</a></span>
</div>
</div>
JSONfile: returns some names,
x.name is dynamically generated from the mentioned JSONfile, and it should be used as a plain text like "NAME", if I add NAME instead of i.name I get the json file loaded, but i want it automatically loaded, because I don't know which of the names will come first.
the i.name returns this:
n
a
m
e
not "NAME" as it should..
So, the question is, is there any way to tell angular that i want this dynamically generated value to be looked as I typed it?
PS.
x.name loads a JSON file with some info about a person.
If i type ng-repeat="i in Tom" it will return the json, but with x.name it doesn't work.
Thanks!
EDIT (added json):
var brojVijesti = [ ];
$scope.JSONfile = brojVijesti;
// LNG Json
$http.get("/LEADERBOARDv2/jsons/LNG.php").then(function(response) {
var LNG = response.data.LNG;
$scope.LNG = LNG;
$scope.LNGbroj = LNG.length;
brojVijesti.push({"name":"LNG", "number":LNG.length});
});
// DT JSON
$http.get("/LEADERBOARDv2/jsons/DT.php").then(function (response) {
var DT = response.data.DT;
$scope.DT = DT;
$scope.DTbroj = DT.length;
brojVijesti.push({"name": "DT", "number": DT.length});
});
I believe you want i in x not i in x.name
Edit: You can then use the $parse dependency which will grab the variable of that specific name from $scope.
<div ng-repeat="x in JSONfile">
<div ng-repeat="i in x">
<span><a ng-href="{{i.link}}">{{getVariable(i.name)}}</a></span>
</div>
</div>
JS:
$scope.getVariable = function(variableName) {
//evaluate the variable name in scope's context.
return $parse(variableName)($scope);
}

Dynamically set v-for with vue.js

So I'm using Vue.js in my project, and I've got a problem: how could I bind filter for v-for dynamically? At some moment of time I'm passing the id of element to the vue method, how could I then put it into v-for item in items | filterBy #{id} in 'id'?
I've tried just putting 'v-for' attribute by JQuery 'attr', but this does not seem to work. I suppose that Vue.filter or vm.$set should be used here, but I can't figure anything out yet.
Would appreciate any possible help!
For example:
var vm = new Vue({
...
methods: {
bindId: function(id) { //id is passed from html
var repeat = 'item in items | filterBy "' + id + '" in "id"';
$(#main).children('.collection').attr('v-for', repeat);
}
}
}
You can just use a variable in your v-for attribute:
v-for item in items | filterBy id in 'id'
var vm = new Vue({
...
data:function() {
return {
id:1
}
}
}
Then you could use v-model on an input like text or select, and set the id there:
<input v-model="id"> <!-- Filter to the id inputted here -->
A few examples here: https://vuejs.org/api/#filterBy

Conditionally setting orderBy Angularjs

I have an array of users, I want to have my ng-repeat ordered by last name when first loaded. After a new user is added have the ng-repeat ordered by dated added then last name. Essentially I want the newest users pushed to the top of the ng-repeat.
<th ng-click="menuFilter('lastName', 1);">
<div ng-class='{"menuSort":sortColumn==1}'>Name <span ng-show="share.orderByField == 'lastName'">
</div>
</th>
<tr ng-repeat="user in users | orderBy:orderByField:reverseSort"></tr>
In my JS...
_this.sortColumn = 1;
_this.orderByField = 'lastName';
_this.reverseSort = false;
_this.menuFilter = function(section, column) {
_this.orderByField = section;
_this.reverseSort = !_this.reverseSort;
_this.sortColumn = column;
};
//my attempt to reset the order by created at date
if( _this.isRefreshing ) {
_this.orderByField = ['createdAt', 'lastName'];
}
Basically this code is not doing anything. I think I am missing a step in the HTML.
Thanks!
I think this is easiest done by sorting the array in pure javascript and then using a ng-repeat without the orderBy attribute.
HTML:
<div ng-repeat="user in users">{{user}}</div>
<input type="text" ng-model="name"></input>
<button ng-click="addName()">Add name</button>
JS:
$scope.users = ["Rusty", "Shackleford", "Dale", "Gribble"];
$scope.users.sort();
$scope.addName = function() {
$scope.users.unshift($scope.name);
}
JSFiddle: http://jsfiddle.net/asWF9/2/
This answer may help to sort your array: https://stackoverflow.com/a/6712080/3675149
Try using "unshift" instead of 'push' to add an item into the array. The unshift in js enables us to insert an item to the top of an array.

Using custom filter on ng-repeat causing ng-class-even/odd not to work

I have a simple ng-repeat with a couple of filters applied. Now I have added an ng-class-even class for the even results and when the filter is applied, the classes seem to remain with the original index before the filter is run. This leaves rows in odd positions with the class 'even'.
HTML
<div data-ng-repeat="location in locations | topBranchFilter:topLocations | cityFilter:searchCity | filter:search" data-ng-class-even="'even'">
...
</div>
Filter (both custom filters use this simple format)
angular.module('App')
.filter('cityFilter', function() {
return function( locations, searchCity ) {
if (searchCity!=='') {
var filtered = [];
angular.forEach(locations, function(location) {
if(location.BranchStationCity==searchCity){
filtered.push(location);
}
});
return filtered;
} else {
return locations;
}
};
});
I guess my question is, is ng-class-even not supported with custom filters or multiple filters?
If you add 'track by $index' to your ng-repeat, it should fix this problem.
<div data-ng-repeat="location in locations | topBranchFilter:topLocations | cityFilter:searchCity | filter:search track by $index" data-ng-class-even="'even'">

Angular Checking What Filters Return

I have a list with ng-repeat and a filter , the filter filters based on an html input . If the filter produces an empty list , I want to show the user some informative message . I can't figure out how...
Search the list: <input type="text" ng-model="searchText">
<div ng-controller="my-ctrl">
<ul id="list">
<li ng-repeat="element in myElements | filter:searchText" >
{{element.data }}
</li>
</ul>
***<div>{{myElements.length}}</div>*** //length stays
// the same no matter what the filter is returning...
<div ng-show="myElements.length">My Informative Msg</div>
What I tried doing was showing my informative msg based on myElements.length , I thought that the filter will update the value of myElements in my scope . However , what I find as I search for items (e.g reducing or enlarging the list) is that myElements.length stays the same .
Is there some elegant solution to know when the filter is empty , or more generally to know what the filter is returning ?
There is a neat trick for that. Instead of filtering the real list, create a new filtered list "in the fly" which will contain only the filtered items or none. If none, show the message.
app.controller('MainCtrl', function($scope) {
$scope.items = ["Foo", "Bar", "Baz"];
});
And:
<input ng-model="searchText" />
<ul>
<li ng-repeat="item in filteredItems = (items | filter: searchText)">
{{ item }}
</li>
</ul>
<div ng-hide="filteredItems.length">There is no item matching</div>
So if your filter doesn't match any item, you will see the message.
Plunker here: http://plnkr.co/edit/3os7gIxSjlyDO1CGKcFT?p=preview
I think you should create your own filter which will do that.
Here it is: http://jsfiddle.net/QXSR8/
HTML
<div>
{{answer | empty}}
</div>
JS
angular.module('project', []).
filter('empty', function() {
return function(input) {
if (!input || !input.length){
return "Array is empty";
} else {
return input;
}
}
});

Categories