Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
37
rated 0 times [  40] [ 3]  / answers: 1 / hits: 23536  / 11 Years ago, fri, september 27, 2013, 12:00:00

I'm having trouble trying to initialize a filter with asynchronous data.



The filter is very simple, it needs to translate paths to name, but to do so it needs a correspondance array, which I need to fetch from the server.



I could do things in the filter definition, before returning the function, but the asynchronous aspect prevents that



angular.module('angularApp').
filter('pathToName', function(Service){
// Do some things here

return function(input){
return input+'!'
}
}


Using a promise may be viable but I don't have any clear understanding on how angular loads filters.
This post explains how to achieve such magic with services, but is it possible to do the same for filters?



And if anyone has a better idea on how to translate those paths, I'm all ears.



EDIT:



I tried with the promise approch, but something isn't right, and I fail to see what:



angular.module('angularApp').filter('pathToName', function($q, Service){

var deferred = $q.defer();
var promise = deferred.promise;

Service.getCorresp().then(function(success){
deferred.resolve(success.data);
}, function(error){
deferred.reject();
});

return function(input){
return promise.then(
function(corresp){
if(corresp.hasOwnProperty(input))
return corresp[input];
else
return input;
}
)
};
});


I'm not really familliar with promises, is it the right way to use them?


More From » angularjs

 Answers
4

Here is an example:



app.filter(testf, function($timeout) {
var data = null, // DATA RECEIVED ASYNCHRONOUSLY AND CACHED HERE
serviceInvoked = false;

function realFilter(value) { // REAL FILTER LOGIC
return ...;
}

return function(value) { // FILTER WRAPPER TO COPE WITH ASYNCHRONICITY
if( data === null ) {
if( !serviceInvoked ) {
serviceInvoked = true;
// CALL THE SERVICE THAT FETCHES THE DATA HERE
callService.then(function(result) {
data = result;
});
}
return -; // PLACEHOLDER WHILE LOADING, COULD BE EMPTY
}
else return realFilter(value);
}
});


This fiddle is a demonstration using timeouts instead of services.






EDIT: As per the comment of sgimeno, extra care must be taken for not calling the service more than once. See the serviceInvoked changes in the code above and the fiddles. See also forked fiddle with Angular 1.2.1 and a button to change the value and trigger digest cycles: forked fiddle






EDIT 2: As per the comment of Miha Eržen, this solution does no logner work for Angular 1.3. The solution is almost trivial though, using the $stateful filter flag, documented here under Stateful filters, and the necessary forked fiddle.



Do note that this solution would hurt performance, as the filter is called each digest cycle. The performance degradation could be negligible or not, depending on the specific case.


[#75392] Thursday, September 26, 2013, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
andrewb

Total Points: 259
Total Questions: 124
Total Answers: 90

Location: Ivory Coast
Member since Sun, Mar 7, 2021
3 Years ago
;