Skip to content

Instantly share code, notes, and snippets.

@davemecha
Last active June 7, 2016 13:19
Show Gist options
  • Save davemecha/0e01c2e32f9077b062246916173a5897 to your computer and use it in GitHub Desktop.
Save davemecha/0e01c2e32f9077b062246916173a5897 to your computer and use it in GitHub Desktop.
Filter as a workaround for a $digest loop problem with angular-meteor in custom filters.
/*******************************************************************************
* @author: Dave Gööck<dave@goeoeck.net>
*
* This small filter is just a workaround for some problem with angular-meteor.
*
* It doesn't really filter any element of the input array but returns a clone
* of the input. The clone is the same instance for each input configuration.
* It's not a deep clone. If the input array contains objects, the result array
* will contain the same instances.
*
* Problem:
* Using custom filters with ngRepeat in templates can cause a digest
* loop, that's only happening in angular without meteor. So migrating filters
* can be painful.
* Described here: http://stackoverflow.com/questions/37602855/custom-filters-produces-infinit-digest-loop-with-angular-meteor
*
* Usage:
* 1. Add this filter to the base module of your project.
* 2. Use it in your template as the last filter applied in a chain:
*
* ng-repeat="vm.items | customFilter | fixLoopFilter"
*
* Drawbacks:
* This filter can be performance and memory consuming for large input array or
* objets. It is just meant as a workarount till the issue is fixed or there is
* a better workaround for this issue.
*
* Dependency: CryptoJS.SHA1
* https://github.com/dandv/meteor-crypto-sha1
* Install CryptoJS.SHA1 by "meteor add crypto-sha1"
******************************************************************************/
.filter('fixLoopFilter', () => {
// Singleton instanceCache, holding one singleton instance for each input
// configuration.
const instanceCache = {};
// Pass through filter function, creating or filling a clone instance for
// the given input.
return (items) => {
// Hash of the given items array.
const hash = CryptoJS.SHA1(angular.toJson(items)).toString();
// Create new result array instance, if there is none in the cache for
// this input.
if (!instanceCache[hash]) instanceCache[hash] = [];
// Clear the cache instance
instanceCache[hash].length = 0;
// Fill the instance with the items (maybe Array.map is not the best choice here).
items.map((item) => {
instanceCache[hash].push(item);
});
// Return cloned data
return instanceCache[hash];
};
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment