Reputation: 6141
I have an AngularJS SPA. During the app's init I get a theme from the server, which includes a couple CSS URLs.
I want to use these, and fallback to a default if they 404.
I thought I could setup a simple directive to accomplish this but I can't get it to work right.
.directive('errorHref', function() {
return {
link: function(scope, element, attrs) {
element.bind('error', function() {
attrs.$set('ng-href', attrs.errorHref);
});
}
}
});
HTML: note, the controller is working; however, _init events in headController are firing before everything else.
<html ng-app="timeclock">
<head ng-controller="headController">
<link ng-href="{{urlToAppCSS}}" error-href="content/css/app.css" rel="stylesheet">
Is this the right approach or is there a better way? Everything seems like it should be functioning properly (and works in almost identical situations in other parts of my app), but the element.bind('error'...
function never actually fires.
Upvotes: 2
Views: 2053
Reputation: 6141
I ended up keeping it really basic just making an $http call in my controller and changing the href value if needed, seems to work very cleanly. Loads up the CSS hard coded into the link tag, then when my theme gets loaded up an event fires triggering the controller's code, swapping out the href value on $http success.
<link id="appCSS" href="content/css/app.css" rel="stylesheet">
Controller
var appCSS = angular.element('#appCSS');
// Try appCSS
$http.get(theme.urlToAppCSS).then (function (response) {
// GET succeeded, load up new CSS
appCSS.attr('href', theme.urlToAppCSS);
}, function (err) {
// GET failed, keep default CSS in place
});
Upvotes: 0
Reputation: 4538
I'm not sure that <link>
elements trigger an error event. So I'd suggest using a directive and <style>
elements. Note that there are a lot of ways to potentially do something like this, and this is just an over-simplified example:
.directive('customStyle', function($http) {
return {
restrict: 'E',
scope: {
href: '@',
fallback: '@'
},
link: function(scope) {
$http.get(scope.href)
.then(function(response) {
// Take the contents of the response and place into
// a scope variable for use in the template
scope.css = response.data;
})
.catch(function(response) {
// The request failed, so instead try loading from scope.fallback url.
});
},
template: '<style>{{ scope.css }}</style>'
}
});
HTML:
<custom-style href="{{ urlToAppCSS }}" fallback="content/css/app.css"></custom-style>
You'd probably want to load the fallback CSS simultaneously so that there's not a long delay in case the requested CSS file couldn't be loaded, but this could be a good starting point.
Upvotes: 1