I originally answered your question in a very complex method that matched your callbacks. Then I re-read your question, and realized that wasn't the goal. The goal is to create something that either shows an image or a frame. Assuming that frame needs to get outside of your domain (based on your usage of $sce, I believe that to be the case), this solution will work.
Full Plnkr: http://embed.plnkr.co/jTmWOLMN7LdiCZPIvuof/preview
HTML:
<body ng-app='myApp' ng-controller="myAppController">
<h1>Hello StackOverflow!</h1>
<iframe-nanny desired-uri="desiredFrameSource" error-image-uri="errorImageSrc"></iframe-nanny>
</body>
Controller:
myAppName.controller("myAppController", function($scope, $sce) {
$scope.desiredFrameSource = 'http://www.w3schools.com/test';
$scope.errorImageSrc = 'https://cdn2.iconfinder.com/data/icons/contact-flat-buttons/512/thumb_down-512.png';
});
We define our URL's in the controller for convenience. These can obviously be variable. To test a failed URI, we can use
$scope.desiredFrameSource = 'http://www.w3schools.com/test';
to test a successful URI:
$scope.desiredFrameSource = 'http://www.w3schools.com/';
Simple enough I hope. The magic happens in the directive now. It either emits an iframe or an image, depending on the results of a YQL query. If you need additional alerts, you can send in callbacks/attributes to the directive and do cute things with it.
Directive:
myAppName.directive('iframeNanny', function($q, $http, $compile, $sce) {
return {
restrict: 'E',
scope: {
desiredUri: '=',
errorImageUri: '='
},
link: function(scope, element, attrs) {
var loadedUri = '';
function isURLReal(fullyQualifiedURL) {
var URL = encodeURIComponent(fullyQualifiedURL);
var dfd = $q.defer();
var yqlUri = 'http://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url%3D%22' + URL + '%22&callback=JSON_CALLBACK';
$http.jsonp(yqlUri)
.success(function(data, status) {
console.log(data.results.length);
if (data.results.length) {
console.log('success!')
dfd.resolve(true);
} else {
dfd.reject(false);
}
}).error(function(data, status) {
dfd.reject('failed');
});
return dfd.promise;
}
scope.$watch('desiredUri', function(uri) {
if (loadedUri !== uri) {
isURLReal(uri).then(function() {
console.log('directive: uri valid');
loadedUri = uri;
scope.trustedUri = $sce.trustAsResourceUrl(scope.desiredUri);
var iFrameHtml = '<iframe src="{{trustedUri}}" frameborder="0" width="100%" height="1100px" scrolling="auto"></iframe>';
var markup = $compile(iFrameHtml)(scope);
element.empty();
element.append(markup);
}).catch(function() {
console.log('directive: uri invalid');
var badRequestImgHtml = '<img src="{{errorImageUri}}">';
var markup = $compile(badRequestImgHtml)(scope);
console.log(scope.errorImageUri);
element.empty();
element.append(markup);
});
}
});
}
};
});
This has been an interesting problem to solve. Great question!