Angular JS functions with multiple parameters - angularjs

In my angular factory I have 3 functions that return the names of some codes, depending on their type: eat, feel and source. This is one of the functions
getFeelingCode: function(feelingCode) {
var feelTag=$filter('filter')(constant.feeling_code, {code: feelingCode}, function(a, b) {
return a === b;
});
if(feelTag[0])
return feelTag[0].label;
else
return feelingCode;
}
The 3 functions bassically do the same thing, and I would like to convert them into one function, that would look like this:
vApp.factory('BgsFactory', function(constant, $filter) {
return {
getCode: function(Code, StringCode) {
var cst;
switch(StringCode) {
case "eating_code": cst = constant.eating_code; break;
case "feeling_code": cst = constant.feeling_code; break;
case "source_code": cst = constant.source_code; break;
}
var Tag=$filter('filter')(cst, {code: Code}, function(a, b) {
return a === b;
});
if(Tag[0])
return Tag[0].label;
else
return Code;
}
In my view I'm calling them like that
<td>{{getSourceCode(item.tags.source)}}</td>
<td>{{getEatingCode(item.tags.eat_code)}}</td>
<td>{{getFeelingCode(item.tags.feeling_code)}}</td>
But I don't know how to set them in my controller. I tried something like that, but it fails saying that the functions don't exist.
$scope.getEatingCode = BgsFactory.getCode("eating_code");
$scope.getFeelingCode = BgsFactory.getCode("feeling_code");
$scope.getSourceCode = BgsFactory.getCode("source_code");
How should I pass the params?
Thank you!

If I wasn't get is wrong, would be like this
$scope.getEatingCode = function(code) { return BgsFactory.getCode(code, "eating_code"); };
$scope.getFeelingCode = function(code) { return BgsFactory.getCode(code, "feeling_code"); };
$scope.getSourceCode = function(code) { return BgsFactory.getCode(code, "source_code"); };

Related

Issue using filter AngularJS

I'm using $filter to iterate through an array and fetch a specific value
Below is my code:
var selected = $filter('filter')($scope.folders, {url: el.selected[0] });
This code is working, but I got a problem when the url contain an accent and space like so :
/Users/Me/project/products/Poste à souder
In that case the string comparaison isn't working anymore.
What is the cleaner way to solve this situation ?
That true. As a francophone, I've often encounter encoding/decoding issues with angularjs.
The source code of the default filter is as follow
function filterFilter()
{
return function(array, expression, comparator)
{
if (!isArrayLike(array))
{
if (array == null)
{
return array;
}
else
{
throw minErr('filter')('notarray', 'Expected array but received: {0}', array);
}
}
var expressionType = getTypeForFilter(expression);
var predicateFn;
var matchAgainstAnyProp;
switch (expressionType)
{
case 'function':
predicateFn = expression;
break;
case 'boolean':
case 'null':
case 'number':
case 'string':
matchAgainstAnyProp = true;
//jshint -W086
case 'object':
//jshint +W086
predicateFn = createPredicateFn(expression, comparator, matchAgainstAnyProp);
break;
default:
return array;
}
return Array.prototype.filter.call(array, predicateFn);
};
}
and the predicate generator stand as follow: it generate the default comparator if the provided one is not a function
function createPredicateFn(expression, comparator, matchAgainstAnyProp)
{
var shouldMatchPrimitives = isObject(expression) && ('$' in expression);
var predicateFn;
if (comparator === true)
{
comparator = equals;
}
else if (!isFunction(comparator))
{
comparator = function(actual, expected)
{
if (isUndefined(actual))
{
// No substring matching against `undefined`
return false;
}
if ((actual === null) || (expected === null))
{
// No substring matching against `null`; only match against `null`
return actual === expected;
}
if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual)))
{
// Should not compare primitives against objects, unless they have custom `toString` method
return false;
}
actual = lowercase('' + actual);
expected = lowercase('' + expected);
return actual.indexOf(expected) !== -1;
};
}
predicateFn = function(item)
{
if (shouldMatchPrimitives && !isObject(item))
{
return deepCompare(item, expression.$, comparator, false);
}
return deepCompare(item, expression, comparator, matchAgainstAnyProp);
};
return predicateFn;
}
Too much speech. You have the choice:
Provide a comparator to your filter see the doc
but remember that you can't define inline function in angular template
you can define a function in that scope, but it will only be available in that scope
You can write your own filter
.filter('myCustomFilter', function()
{
return function(input, criteria)
{
... // your logic here
return ...// the filtered values
};
})
Maybe it's best to write your own filter:
app.filter("customFilter", function () {
//the filter will accept an input array, the key you want to look for and the value that the key should have
return function (array, key, value) {
return array.filter(function(x){
return (x.hasOwnProperty(key) && (x[key] === value));
});
};
});
And use it in your controller like:
$scope.filtered = $filter("customFilter")($scope.folders, "url", "/Users/Me/project/products/Poste à souder");
Check out a working demo here.

How to reuse functions in an AngularJS factory?

I have an AngularJS factory for some common local storage manipulation. It's a common set of functions against different variables. I am constructing it so that the functions are repeated depending on which variable needs to be manipulated. Likely not an elegant way to go about this so open to options.
The factory looks as follows. Is there a way to reuse functions depending on the variable without so much code bloat?
angular.module('app.datastore', [])
.factory('DataStore', function() {
var venue = angular.fromJson(window.localStorage['venue'] || '[]');
var prize = angular.fromJson(window.localStorage['prize'] || '[]');
function persist_venue() {
window.localStorage['venue'] = angular.toJson(venue);
}
return {
list_venue: function () {
return venue;
},
get_venue: function(venueId) {
for (var i=0; i<venue.length; i++) {
if (venue[i].id === venueId) {
return venue[i];
}
}
return undefined;
},
create_venue: function(venueItem) {
venue.push(venueItem);
persist_venue();
},
list_prize: function () {
return prize;
},
get_prize: function(prizeId) {
for (var i=0; i<prize.length; i++) {
if (prize[i].id === prizeId) {
return prize[i];
}
}
return undefined;
},
create_prize: function(prizeItem) {
venue.push(prizeIem);
persist_prize();
}
};
});
My approach is to return in the factory a function which will return a store of a type (venue, prize, ...)
angular.module('app.datastore', [])
.factory('DataStore', function () {
var getStoreFunction = function (storeName) {
var store = angular.fromJson(window.localStorage[storeName] || '[]');
function persist() {
window.localStorage[storeName] = angular.toJson(store);
};
return {
list: function () {
return store;
},
getItem: function (id) {
return store.find(function (elem) {
return elem.id === id;
});
},
createItem: function (item) {
store.push(item);
persist(store);
}
}
};
return { getStore : getStoreFunction };
});
you can create unlimited store by using
var venueStore = DataStore.getStore('venue');
//use of your store
venueStore.createItem({
id : venueStore.list().length + 1,
name : 'myVenue' + venueStore.list().length + 1
});
$scope.venues = venueStore.list();
you can create a factory per type if you want or use it directly in your controller as in this example : https://jsfiddle.net/royto/cgxfmv4q/
i dont know if your familiar with John Papa's angular style guide but you really should take a look it might help you with a lot of design questions.
https://github.com/johnpapa/angular-styleguide
anyway - i would recommend you use this approach -
angular.module('app.datastore', [])
.factory('DataStore', function () {
var venue = angular.fromJson(window.localStorage['venue'] || '[]');
var prize = angular.fromJson(window.localStorage['prize'] || '[]');
return {
list_venue: list_venue,
persist_venue: persist_venue,
get_venue: get_venue,
create_venue: create_venue,
list_prize: list_prize,
get_prize: get_prize,
create_prize: create_prize
};
function persist_venue() {
window.localStorage['venue'] = angular.toJson(venue);
}
function list_venue() {
return venue;
}
function get_venue(venueId) {
for (var i = 0; i < venue.length; i++) {
if (venue[i].id === venueId) {
return venue[i];
}
}
return undefined;
}
function create_venue(venueItem) {
venue.push(venueItem);
persist_venue();
}
function list_prize() {
return prize;
}
function get_prize(prizeId) {
for (var i = 0; i < prize.length; i++) {
if (prize[i].id === prizeId) {
return prize[i];
}
}
return undefined;
}
function create_prize(prizeItem) {
venue.push(prizeIem);
persist_prize();
} });
i like this approach because on the top you can see all the functions available in this factory nice and easy,
and you can also reuse every function you expose outside, inside also, so its very effective and organized,
hope that helped,
good luck.

checkbox filter for json array in Angularjs

I have create a filter but this filter is not working with array inside array.
'http://plnkr.co/edit/oygy79j3xyoGJmiPHm4g?p=info'
Above plkr link is working demo.
app.filter('checkboxFilter', function($parse) {
var cache = { //create an cache in the closure
result: [],
checkboxData: {}
};
function prepareGroups(checkboxData) {
var groupedSelections = {};
Object.keys(checkboxData).forEach(function(prop) {
//console.log(prop);
if (!checkboxData[prop]) {
return;
} //no need to create a function
var ar = prop.split('=');
//console.log("ar is - "+ar);
if (ar[1] === 'true') {
ar[1] = true;
} //catch booleans
if (ar[1] === 'false') {
ar[1] = false;
} //catch booleans
/* replacing 0 with true for show all offers */
if(ar[0]=='SplOfferAvailable.text'){
ar[1]='true';
}else{
}
//make sure the selection is there!
groupedSelections[ar[0]] = groupedSelections[ar[0]] || [];
//at the value to the group.
groupedSelections[ar[0]].push(ar[1]);
});
return groupedSelections;
}
function prepareChecks(checkboxData) {
var groupedSelections = prepareGroups(checkboxData);
var checks = [];
//console.log(groupedSelections);
Object.keys(groupedSelections).forEach(function(group) {
//console.log("groupedSelections- "+groupedSelections);
//console.log("group- "+group);
var needToInclude = function(item) {
//console.log("item- "+item);
// use the angular parser to get the data for the comparson out.
var itemValue = $parse(group)(item);
var valueArr = groupedSelections[group];
//console.log("valueArr- "+valueArr);
function checkValue(value) { //helper function
return value == itemValue;
}
//check if one of the values is included.
return valueArr.some(checkValue);
};
checks.push(needToInclude); //store the function for later use
});
return checks;
}
return function(input, checkboxData, purgeCache) {
if (!purgeCache) { //can I return a previous 'run'?
// is the request the same as before, and is there an result already?
if (angular.equals(checkboxData, cache.checkboxData) && cache.result.length) {
return cache.result; //Done!
}
}
cache.checkboxData = angular.copy(checkboxData);
var result = []; // this holds the results
//prepare the checking functions just once.
var checks = prepareChecks(checkboxData);
input.every(function(item) {
if (checks.every(function(check) {
return check(item);
})) {
result.push(item);
}
return result.length < 10000000; //max out at 100 results!
});
cache.result = result; //store in chache
return result;
};
});
above code is for check box filter.
when i click on checkbox called "Availability" it does not filter the result.
Please help me out.
Thanks.
I think that the way you are navigating through json is wrong because if you put in this way it works
"Location": "Riyadh",
"AvlStatus": "AVAILABLE"
"Rooms": {.....
You have to go in some way through Rooms and right now I think you're not doing that

Angular filter causing infidig error

I have the following angular filter being used into an ng-repeat that's causing a infidig error, and I can't understand how to fix it:
app.filter('orderByTime', function() {
return function(items) {
return items.sort(function(a, b) {
a = moment(a.departure.time, "HH:mm");
b = moment(b.departure.time, "HH:mm");
if (a.isAfter(b)) {
return 1;
}
if (a.isBefore(b)) {
return -1;
}
return 0;
});
};
});
moment is from the library moment.js. The intent of this filter is to order a list of flight by the time of departure.
After a bit of discussion in the comments, the problem is caused by how I'm assigning the value to the variable:
$scope.flightList = []
var url = '/api/schedule/' + $rootScope.depAriportIATA;
if ($rootScope.desAriportIATA) {
url += '/' + $rootScope.desAriportIATA;
}
$http.get(url).success(function(flights) {
$scope.flightList = flights;
});

Getting the response from an angular function

I have the following scope function in my controller
$scope.getStaff = function (request, response) {
var a = [];
if ($scope.staff !== null) {
// all terms must be contained
a = $scope.staff;
var terms = request.term.toLowerCase().split(' ');
for (var i = 0; i < terms.length; i++) {
var t = terms[i];
if (t) {
a = $.grep(a, function (item, index) {
var v = item.label.toLowerCase();
return v.indexOf(t) !== -1;
});
}
}
}
response(a.length > 0 ? a : null);
};
I'm attempting to test it using jasmine like this:
describe('getStaff', function() {
it('...', function() {
$scope.staff = [
{ label: "test1" },
{ label: "test2" }
];
var req = { term: "a b c" };
expect(req.term.toLowerCase()).toBe('a b c');
var res = function(a) {
return a;
}
var result = $scope.getStaff(req, res).response;
expect(result).toBe(null);
});
});
I'm ultimately trying to see what "a" is in the getStaff function. How can I get that value in my jasmine test?
My answer is really an opinion. Unless you are willing to expose your 'a' in the scope of the controller, then my answer would be "you don't care" your jasmine test should only be testing the answer of response(a.length > 0 ? a : null); returned.
My gut tells me you may want to consider creating a helper function for this code
$.grep(a, function (item, index) {
var v = item.label.toLowerCase();
return v.indexOf(t) !== -1;
});
and unit testing that separate from your getStaff function.

Resources