Search code examples
angularjsangular-filters

Angular: how to make a configurable filter


Is it possible to create a configurable filter the way you can create configurable services:

angular.module('app', [])
       .provider('resourceUrl', function($filterProvider) { 

    var base = '/';

    this.setPrefix = function(prefix) {base = prefix};

    $filterProvider.register('resourceUrl', resourceUrlFilter);

    this.$get = ??

    function resourceUrlFilter(url) { /* returns the new url */ }
})

I wan't to create a filter that adds a base url prefix to a path string and the url prefix should be configurable.

Currently I achieve this by injecting a constant in the filter

angular.module('app', [])
       .constant('baseUrl', '...')
       .filter('resourceUrl', ['baseUrl', function(baseUrl) {

       return function resourceUrlFilter(url) { /* returns the new url */ }
}]

Solution

  • I had a reminder of this question today, and recently I had to use some filters in a service, and this crossed my mind:

    Since to inject a filter into a service let's say I have created the customDate filter, I have to provide the name customDateFilter in order to inject it

     myModule.factory('MyData', function(customDateFilter) { /* code */ });
    

    So I thought:

    Maybe I can register a filter the same way I register a service but then append Filter to the name, and it worked.

    I don't know if it is considered legal to register a filter in this way, or whether it won't be dropped in the future but this is a way that allows you to register a filter with a provider


    The short version:

    You can register a configurable filter, by creating a ServiceProvider the way usual configurable services are created -> https://docs.angularjs.org/guide/providers#provider-recipe But when you register the ServiceProvider append Filter to the service name:

    JS
    var module = angular.module('app', [])
    var customDate = function filterProvider() { /* ServiceProvider definition */ };
    myModule.provider('customDateFilter', customDate);
    
    HTML
    <p>Some date: <span>{{ $ctrl.date | customDate }}</span> </p>
    

    Working plunk example

    This plunk shows an example of a baseUrl filter that can be configured with a prefix in a module's config block https://plnkr.co/edit/RkTkKM?p=preview


    Other Options

    You can always create a service that performs the filtering and then expose it through a filter by injecting it to the filter factory. And this service can be a configurable service using the Provider Recipe

    class FilteringServiceProvider {
    
        $get() { return new FilteringService(this.configuration) }
    
        configure(params) { /* some config logic */ }
    }
    
    class FilteringService {
    
      constructor(configuration) {}
    
      filterDate(date) { /* some filtering on the date and return a value */ }
    }
    
    const myModule = angular.module('app.filters', []);
    
    myModule
      .provider('filteringService', FilteringServiceProvider)
      .filter('customDate', (filteringService) => filteringService.filterDate);