-
-
Save idosela/8421332 to your computer and use it in GitHub Desktop.
angular.module('myMdl', []).config(['$httpProvider', function($httpProvider) { | |
$httpProvider.responseInterceptors.push([ | |
'$q', '$templateCache', 'activeProfile', | |
function($q, $templateCache, activeProfile) { | |
// Keep track which HTML templates have already been modified. | |
var modifiedTemplates = {}; | |
// Tests if there are any keep/omit attributes. | |
var HAS_FLAGS_EXP = /data-(keep|omit)/; | |
// Tests if the requested url is a html page. | |
var IS_HTML_PAGE = /\.html$|\.html\?/i; | |
return function(promise) { | |
return promise.then(function(response) { | |
var url = response.config.url, | |
responseData = response.data; | |
if (!modifiedTemplates[url] && IS_HTML_PAGE.test(url) && | |
HAS_FLAGS_EXP.test(responseData)) { | |
// Create a DOM fragment from the response HTML. | |
var template = $('<div>').append(responseData); | |
// Find and parse the keep/omit attributes in the view. | |
template.find('[data-keep],[data-omit]').each(function() { | |
var element = $(this), | |
data = element.data(), | |
keep = data.keep, | |
features = keep || data.omit || ''; | |
// Check if the user has all of the specified features. | |
var hasFeature = _.all(features.split(','), function(feature) { | |
return activeProfile.features[feature]; | |
}); | |
if (flags.features.length && | |
((keep && !hasFeature) || (!keep && hasFeature))) { | |
element.remove(); | |
} | |
}); | |
// Set the modified template. | |
response.data = template.html(); | |
// Replace the template in the template cache, and mark the | |
// template as modified. | |
$templateCache.put(url, response.data); | |
modifiedTemplates[url] = true; | |
} | |
return response; | |
}, | |
// Reject the response in case of an error. | |
function(response) { | |
return $q.reject(response); | |
}); | |
}; | |
}]); | |
}]); |
ng-if will remove the dom element, which this doesn't
Is there any benefit in not doing it with a custom directive? If I were to do this, I would parse them in request interceptor instead the response. So, that I can tell the server not to send me unnecessary data.
Can't the user just use Firebug or any debugging tools to inspect the result of the XHR request, before the data-keep bits are removed by Angular?
@ziaxdk, This actually removes the DOM element from the template before it even gets to angular so technically using this would remove the need for angular to process the ngIf.
@sebastienbarre I believe you are correct on that however this for me is more about performance gains than hiding HTML from the user.
To answer my own question, I guess this would be more performant then just using ngIf since it would remove the need to process the ngIf on each update of the DOM instead of just once per template.
Why make Angular process/evaluate extra directives (even if you wrote a very performant one) when you don't need to? It is a point/question of performance.
There may be somewhat of a security gain (in that it's a bit more obfuscated from the user), but @sebastienbarre is right in that it's not exactly enough - but security is not the primary intention of this pattern. (The user could just examine the XHR response. You could load templates into the $templateCache beforehand using a Grunt task like ng-templates, but the user could still examine the $templateCache.)
@hasdavidc @torifat the benefit? cache! you grab the same template for different set of, let's say, options
watch http://www.youtube.com/watch?v=62RvRQuMVyg for more ;-)
👍
Just updated my fork of this that is compatible with angular 1.3.x (since $httpProvider.responseInterceptors
in no longer valid) : https://gist.github.com/ryanzec/8461975
Has anyone noticed that flags
for the test flags.features.length
is not defined? Should this be just features.length
?
would this gain any performance compared to just doing ng-if since from my understanding, angular will not process anything within an if statement that is evaluates to false?