AngularJS: Apply filter to template - angularjs

I created a simple filter to format a number based on the current locale.
angular.module('myApp').filter('doubleFilter', DoubleFilter);
function DoubleFilter($translate) {
return function(val, decimalPlaces) {
if (val && (typeof val === 'number')) {
val = val.toFixed(decimalPlaces);
if ($translate.use() === 'de_DE') {
val = val.replace('.', ',');
}
}
return val;
}
};
I call this filter in my template like this and it works fine:
{{dog.weight | doubleFilter : 2}}
However when I change the language using $translate.use('en_US') the format of the numbers in my template are not updated. Obviously I am missing out on something here.
How can I update the view when the language changes?

I think your directive needs to listen for 'local changed notification', for example :
scope.$on('$localeChangeSuccess', function () {
// code to execute the filter
});

Making your filter stateful may help ( see https://docs.angularjs.org/guide/filter )

Related

update object using id in angular js

I have an array with two keys like id and selected values its like below
$scope.overview =[{'id':1,'selectedvalues':[a,e,o]},{'id':2,'selectedvalues':[aa,ee,oo]},{'id':3,'selectedvalues':[aaa,eee,ooo]}];
I need to update after i am adding values 'h' for id =1 i need to update my array like
$scope.overview =[{'id':1,'selectedvalues':[a,e,o,h]},{'id':2,'selectedvalues':[aa,ee,oo]},{'id':3,'selectedvalues':[aaa,eee,ooo]}];
there is any other way in anuglar js currently i am handling in javascript like
if (this.selectedCategoryOverview.length > 0) {
for (var i in updateDropown) {
if (catid == updateDropown[i].id){
overviewUpdate = false;
updateDropown[i].selectedValues = tempSelectValuesArray;
}
}
}
if(overviewUpdate){
this.selectedCategoryOverview.push({
'id': catid,
'selectedValues': tempSelectValuesArray
});
}
Try to use array.find to find existing overview by id. If find method returns a value - just update the value, and add the value otherwise.
In pseudocode:
foundObject = array.find()
if(foundObject)
update()
else
pushNew()
It would not make much difference if you do it angular way or JS way unless DOM is involved, so here is one angular way which is nothing but cloated JS way,
function pushNewArrayValue(value){
angular.forEach($scope.overview,function(arr,i){
arr.selectedValue.push(value);
})
}
pusheNewArrayValue('h')
Try using filter,
var found;
if (this.selectedCategoryOverview.length > 0) {
found = $filter('filter')($scope.updateDropown, { id: catid });
if (found.length)
$scope.updateDropown = tempSelectValuesArray;
}
if (found && found.length) {
this.selectedCategoryOverview.push({
'id': catid,
'selectedValues': tempSelectValuesArray
});
}

Filter scope by categories true underscore

I need to filter only posts that have within categories, eg desenvolvimento: true.
I tried to use the underscore , but could not get it back me all the posts, needed only the posts that contain this filter.
$scope.filter = 'desenvolvimento';
$scope.teste = _.where($scope.posts, 'desenvolvimento');
RESOLVED!!! example in JsBin
Follows the JSBin:
https://jsbin.com/turodayaqe/1/edit?html,output
In your case you would need something like:
_.each(obj, function (v1, k1) {
_.each(v1, function(v2){
if(typeof v2 === "object") {
_.each(v2, function(v3){
console.log(v3);
if(v3 === value) {
// do something
}
});
}
});
});
But I'm not quite sure what you want to do.
You can use Array.prototype.filter or underscore's _.filter and just check the existence of the properties chain, and the end result (demo):
$scope.filter = 'artigos';
$scope.resolve = $scope.posts.filter(function (item) {
return !!(item.tax && item.tax.categorias && item.tax.categorias[$scope.filter]); // go over the props chain, if anything is missing it will return false
});

AngularMaterial md-chips : Dont show selected item in <md-autocomplete>

I'm trying the <md-autocomplete> example from here md-chips
To prevent the selected items from coming inside <md-autocomplete> I've modified the querySearch function like this:
function querySearch (query) {
var results = query ? self.searchData.filter(createFilterFor(query)) : [];
var finalResults = [];
angular.forEach(results, function(result) {
if($scope.selectedItems.indexOf(result.name) < 0) {
finalResults.push(result);
updateSelectedItems(result);
}
});
return finalResults;
}
But my problem is that the control does not come inside this function once we select an item. Can someone please explain how to solve this ?
I found the solution from this documentation: md-autocomplete
We just need to add md-no-cache="true" for calling the querySearchfunction each time we search for a query item
The solution that worked for me:
The md-no-cache="true" on md-autocomplete still is a must to force the autocomplete to reinitialize the md-items;
Md-chips should have md-on-remove and md-on-append set and implemented as to remove a chip from the list, or add a chip to the list;
My code looks something like this:
HTML:
md-on-remove="removeTagChip($chip)"
md-on-append="appendTagChip($chip)"
JS:
$scope.removeTagChip = function (chip) {
var chipPos = $scope.getPosition(chip.Id, $scope.ChipTags);
if (chipPos < 0) {
$scope.ChipTags.push(chip);
}
};
$scope.appendTagChip = function (chip) {
var chipPos = $scope.getPosition(chip.Id, $scope.ChipTags);
if (chipPos > -1) {
$scope.ChipTags.splice(chipPos, 1);
}
return chip;
};
$scope.getPosition just returns the position of the chip in the list of chips;

CheckAll/UncheckAll issue with Subscribe ? Knockout

I been trying to do checkbox Checkall and UnCheckall using subscribe and i'm partially successful doing that but i am unable to find a fix in couple of scenarios when i am dealing with subscribe .
Using subscribe :
I am here able to checkAll uncheckAll but when i uncheck a child checkbox i.e test1 or test2 i need my parent checkbox name also to be unchecked and in next turn if i check test1 the parent checkbox should be checked i.e keeping condition both child checkboxes are checked .
For fiddle : Click Here
ViewModel :
self.selectedAllBox.subscribe(function (newValue) {
if (newValue == true) {
ko.utils.arrayForEach(self.People(), function (item) {
item.sel(true);
});
} else {
ko.utils.arrayForEach(self.People(), function (item) {
item.sel(false);
});
}
});
The same scenario can be done perfectly in easy way using computed but due some performance issues i need to use subscribe which is best way it wont fire like computed onload .
Reference : Using computed same thing is done perfectly check this Fiddle
I tried to use change event in individual checkbox binding but its a dead end till now.
Any help is appreciated .
Your subscription only applies to edits on the selectedAllBox. To do what you want, you'll need subscriptions on every Person checkbox as well, to check for the right conditions and uncheck the selectedAllBox in the right situations there.
It strikes me as odd that this would be acceptable but using computed() is not. Maybe you should reconsider that part of your answer. I would much rather compute a "isAllSelected" value based on my viewModel state, then bind the selectedAllBox to that.
I solved a similar problem in my own application a couple of years ago using manual subscriptions. Although the computed observable method is concise and easy to understand, it suffers from poor performance when there's a large number of items. Hopefully the code below speaks for itself:
function unsetCount(array, propName) {
// When an item is added to the array, set up a manual subscription
function addItem(item) {
var previousValue = !!item[propName]();
item[propName]._unsetSubscription = item[propName].subscribe(function (latestValue) {
latestValue = !!latestValue;
if (latestValue !== previousValue) {
previousValue = latestValue;
unsetCount(unsetCount() + (latestValue ? -1 : 1));
}
});
return previousValue;
}
// When an item is removed from the array, dispose the subscription
function removeItem(item) {
item[propName]._unsetSubscription.dispose();
return !!item[propName]();
}
// Initialize
var tempUnsetCount = 0;
ko.utils.arrayForEach(array(), function (item) {
if (!addItem(item)) {
tempUnsetCount++;
}
});
var unsetCount = ko.observable(tempUnsetCount);
// Subscribe to array changes
array.subscribe(function (changes) {
var tempUnsetCount = unsetCount();
ko.utils.arrayForEach(changes, function (change) {
if (change.moved === undefined) {
if (change.status === 'added') {
if (!addItem(change.value))
tempUnsetCount++;
} else {
if (!removeItem(change.value))
tempUnsetCount--;
}
}
});
unsetCount(tempUnsetCount);
}, null, 'arrayChange');
return unsetCount;
}
You'll still use a computed observable in your viewmodel for the the select-all value, but now it'll only need to check the unselected count:
self.unselectedPeopleCount = unsetCount(self.People, 'Selected');
self.SelectAll = ko.pureComputed({
read: function() {
return self.People().length && self.unselectedPeopleCount() === 0;
},
write: function(value) {
ko.utils.arrayForEach(self.People(), function (person) {
person.Selected(value);
});
}
}).extend({rateLimit:0});
Example: http://jsfiddle.net/mbest/dwnv81j0/
The computed approach is the right way to do this. You can improve some performance issues by using pureComputed and by using rateLimit. Both require more recent versions of Knockout than the 2.2.1 used in your example (3.2 and 3.1, respectively).
self.SelectAll = ko.pureComputed({
read: function() {
var item = ko.utils.arrayFirst(self.People(), function(item) {
return !item.Selected();
});
return item == null;
},
write: function(value) {
ko.utils.arrayForEach(self.People(), function (person) {
person.Selected(value);
});
}
}).extend({rateLimit:1});
http://jsfiddle.net/mbest/AneL9/98/

Can I use filter in ng-repeat to filter multiple items for a specific field

I'm working on a filtering solution for a grid. The filter contains multiple checkboxes in a panel. I currently have a working solution that uses the filter built into the ng-repeat directive. However, I haven't found a way to make it filter a single field with multiple parameters. This is what I have:
HTML:
<tr data-ng-repeat="rule in rules | orderBy:sortOrder | filter:filterOrder">
Contoller:
var defaultFilter = {critical:'', score:'', category:'', pass:'false'};
$scope.filterOrder = defaultFilter;
What I would like is to be able to do something like this:
var defaultFilter = {critical:'', score:'', category:'', pass:'false && notRun'};
I'm not sure if this is possible. I've looked for the syntax on it, but I have yet to find it. I know there are ways to put it in the controller, but due to our current project this implementation would be considerably easier.
Assuming you are using the 1.0.x branch, the relevant part of the source code for the filtering on objects is shown in the footnote below. This shows that the standard filter finds the key to test, and then gets var text = (''+expression[key]).toLowerCase(); from your search criteria before calling search. search then does a text search using (indexOf(text) > -1.
Therefore you can't set one of the items in your search criteria to an expression that requires evaluation in the way that you are trying.
Your only other options are to:
use a predicate function as the parameter for the filter (this just needs to return true/false); or
to write your own filter (this just needs to return a new array from the original one).
Predicate function
$scope.myFilterTest(item) { return ... true or false test result ...; }
and:
<tr data-ng-repeat="rule in rules | orderBy:sortOrder | filter:myFilterTest">
custom filter
var someApp=angular.module('myApp', []);
someApp.filter('complexFilter', function() {
return function(input, criteria) {
var result = [];
for (var i = 0; i < input.length; i++) {
if(... multiple tests ...){
result.push(input[i]);
}
}
return result;
}
});
And then:
<tr data-ng-repeat="rule in rules | orderBy:sortOrder | complexFilter:filterOrder">
Footnote:
relevant part of src/ng/filter/filter.js
case "object":
for (var key in expression) {
if (key == '$') {
(function() {
var text = (''+expression[key]).toLowerCase();
if (!text) return;
predicates.push(function(value) {
return search(value, text);
});
})();
} else {
(function() {
var path = key;
var text = (''+expression[key]).toLowerCase();
if (!text) return;
predicates.push(function(value) {
return search(getter(value, path), text);
});
})();
}
}
break;
yes you can achieve this using custom filter, here is the answer for you question.
And fiddle link here
filterMultiple

Resources