Create a nested fallback src for an Image using angularjs directive - angularjs

In my tag if the src returns a 404 then I can display a fallback image using directives, but if this fallback image is also returns 404 the how can I show another image using directive

Create a directive to go through a series of error images and provide them one after the other.
You can provide alternative image urls in the tag itself.
<img fallbacksrc="http://url1/error.jpg,http://url2/error.jpg" src="http://url0.image.jpg">
Then write a directive for fallbacksrc and bind the tag for error event. Use split function to alternative images in to an array. You can then choose from this array inside the link function.
The information you are looking for is that the error event will occur any number of times as long as the src fails. So there is no limit for this to occur if all the images you are setting inside the directive fails continuously.
Here is a sample code. I'm using an array of error images in the scope itself in this example without providing them inside the tag.
function MyCtrl($scope) {
$scope.image = "http://greentreesarborcareinc.com/wp-content/uploads/2014/01/image-placeholder.jpg1"
$scope.errorImageIdx = 0;
$scope.errorImages = ["http://spanning.com/assets/uploads/images/11954453151817762013molumen_red_square_error_warning_icon.svg_.med_.png", "http://fivera.net/wp-content/uploads/2014/03/error_z0my4n.png"]
}
myApp.directive('fallbacksrc', function() {
return {
link: function(scope, ele) {
ele.bind('error', function() {
if (scope.errorImageIdx <= scope.errorImages.length - 1) {
angular.element(this).attr("src", scope.errorImages[scope.errorImageIdx]);
scope.errorImageIdx++;
}
});
}
}
});
Here the tag will try to display the image referenced in $scope.image. But that is invalid. So, it tries to load the images from the array.
Try setting the first element of the array to something invalid. It will automatically select the second image in this case.

You can create angular directive like this -
app.directive('onError', function() {
return {
restrict:'A',
link: function(scope, element, attr) {
element.on('error', function() {
element.attr('src', attr.onError);
})
}
}
});
And use like -
<img class="pic" on-error="default-image.jpg" ng-src="{{author.profileImageUrl}}">

Related

how to include an external html with javascript in iFrame

I am trying to get html with javascript (with relative paths inside this javascript script tag) using rest service and show it in the iFrame in my angularjs application.
basically we are integrating with webfocus and webfocus provides html contents when we call the rest service. This html content has script tag in it and this script tag has relative paths. so when I try to bind that html/javascript to iFrame's contentWindow.document.body I am getting relative path issue.
Any help would be much appreciated.
Angularjs directive is as follows.
.directive("preview", ['$sce',function ($sce) {
function link(scope, element) {
var iframe = document.createElement('iframe');
iframe.setAttribute("id", "ifWebFocusContent");
iframe.setAttribute("name", "nameWebFocusContent");
var element0 = element[0];
element0.appendChild(iframe);
var body = iframe.contentWindow.document.body;
//var body = iframe.document.body;
scope.$watch('content', function () {
body.innerHTML = $sce.trustAsHtml(scope.content);
});
}
return {
link: link,
restrict: 'E',
scope: {
content: '='
}
};
}])
And HTML code is <preview content="reportHtml"></preview>
I used this link to write this code.
It got resolved when I add base tag in the iframe as here
Also used these 3 lines inside watch instead of assigning inner html.
iframe.contentWindow.document.open();
iframe.contentWindow.document.write($sce.trustAsHtml(scope.content));
iframe.contentWindow.document.close()

Syntax highlighted code snippet wont display with AngularJs ngBind

I used some Syntax highlighting API for highlighting code snippet for my web application.To do that i have used highlightjs .I created popup model and inside model i have put <pre> tag and when model open it should display my highlighted xml string.
HTML Code snippet
<pre id="tepXml" ><code class="xml">{{tepXml}}</code></pre>
In AngularJs controller dynamically bind the value to tepXml from server.
AngularJs controller
...$promise.then(function(data){
$scope.tepXml=data.xml;
}
But the problem was that when i open popup model my xml content is empty.nothing display anything.But when i removed <code class="xml"></code> from <pre> xml content would display with out highlighting.I referred some posts and used $compile in angularJs controller but the problem was still the same.
AngularJs controller with $compile
var target = angular.element($window.document.querySelector('#tepXml'));
var myHTML = data.xml;
target.append( $compile( myHTML )($scope) );
If someone knows where i went wrong please point me out.
Plunker
The quick answer is to do:
$promise.then(function(data){
$scope.tepXml=data.xml;
// Call highlight api
$timeout(function() {
$('pre#tepXml code').each(function(i, block) {
hljs.highlightBlock(block); //or whatever the correct highlightjs call is.
});
});
The more Angular way of doing things is to call a jQuery function from Angular is to write a Directive. Something like this:
.directive("highlightCode", function($interval) {
return {
restrict: "A",
scope: { highlightCode: "=" },
link: function(scope, elem, attrs) {
$scope.$watch('highlightCode', function() {
$(elem).find('code').each(function(i, block) {
hljs.highlightBlock(block); //or whatever the correct highlightjs call is.
});
}
}
});
Used like this:
<pre id="tepXml" highlight-code="tepXml"><code class="xml">{{tepXml}}</code></pre>

Dynamic id inside AngularJS template

I'm wrapping a jQuery plugin inside a AngularJS directive. The way I would like to call the directive is for example:
<my-dialog data-trigger-id="myTriggerId">My dialog content...</my-dialog>
Inside my directive template it looks like this:
<button id="{{triggerId}}">Button text...</button>
I attach the event for the jQuery plugin (where you specify the trigger selector) inside the link function of my directive. My problem is that it works if I hardcode the id of the button inside the directive template like this:
<button id="myTriggerId">Button text...</button>
The generated html looks fine in the browser, which means that rendering an element with a dynamic id works. It's just that the jQuery plugin cannot find this element if I use the dynamic id but it works with the hardcoded version.
I also looked up AngularJS compile because it looks like at the point where the jQuery plugin wants to initialize the element doesn't exist yet.
Is there a gotcha I'm missing? Thanks!
Edit: I finally managed to simplify it down and create a jsfiddle example. If you run the example, you will see in the console that the element doesn't exist at the time I'm logging it but if you inspect the DOM, you will see that it's there and has the correct id.
However if you hardcode the id in the template (id=test instead of id={{elemId}}), the console log will show that one element could be found. I hope this helps to find a solution.
http://jsfiddle.net/a1nxyv8u/7/
The digest has not yet rendered in the DOM by the time you are calling you $("#test").length.
You need to add in a $timeout so that the digest will complete, then call your method
var app = angular.module('app', []);
app.directive('myDialog', ['$timeout', function ($timeout) {
return {
restrict: 'E',
template: '<button id="{{elemId}}" class="{{elemClass}}">Open dialog</button>',
link: function (scope, element, attrs) {
var selector = scope.elemSelector,
elemClass = (selector.indexOf('.') > -1) ? selector.substr(1) : '',
elemId = (selector.indexOf('#') > -1) ? selector.substr(1) : '';
scope.elemClass = elemClass;
scope.elemId = elemId;
$timeout(function() {
console.log('elem: ', $('#test').length);
});
// jQuery plugin init here but element doesn't seem to exist yet.
},
scope: {
elemSelector: '#'
}
}
}]);
Although it should be noted that you should try and alleviate any Id's at all and just use $(element) instead unless your jQuery absolutely needs the Id.

Directive custom control

I am trying to create a directive as custom video control. I loading an html file to templateUrl of this directive. The problem is when there are more than one controls, they have the same src file set to all of them and they are sharing state of video as well. When I pause from another control, it pauses video being played on 1st control. Here is directive template that I am using:
dApp.directive('myVideoControl', function(){
return {
scope: {
cameraUrl: '=vcCameraUrl'
},
restrict: 'E',
templateUrl: './../../js/directives/myVideoControl.html',
link: function (scope, element, attrs) {
scope.playVideo = function(){
var v = document.getElementsByTagName("video")[0];
v.play();
}
scope.pauseVideo = function(){
var v = document.getElementsByTagName("video")[0];
v.pause();
}
}
}
});
Will greatly appreaciate if anyone can point out if I am doing anything wrong here.
Thanks.
It looks like the problem you are having is that you are looking up the element by tag name. Basically, every element in your dom with the tag <video> is going to be effected by any use of your directive.
The idea with directives, is that they provide direct access to the element that the directive was assigned. In your case element inside the link function parameters. So you need to reference the individual associated elements like this:
var v = element[0];
v.play();
If you have assigned the directive on a parent element, and want all children, then use the find() jqLite function on the directive element:
var v = element.find('video')[0];
v.play();
var v = document.getElementsByTagName("video")[0];
You are selecting the first video tag in the entire page.
instead get the element inside your template,something like
element.find('video')[0]

Angular navigate to a specific tab on a page

I would like to navigate to a page of my single page application using a link like /#/invoices/1?tab=2. This page contains tabs, so I would also like to send the user directly to the tab I wish through the url.
Could you provide some pointers on how to implement this in the cleanest way?
Use $anchorScroll method, passing a class name on it you can go directly to that element.
Just an update to above answer.
Few examples with custom directives
http://nadeemkhedr.com/angularjs-scroll-to-element-using-directives/
angular.module('MyApp').directive('scrollToBookmark', function() {
return {
link: function(scope, element, attrs) {
var value = attrs.scrollToBookmark;
element.click(function() {
scope.$apply(function() {
var selector = "[scroll-bookmark='"+ value +"']";
var element = $(selector);
if(element.length) {
window.scrollTo(0, element[0].offsetTop – 100);
// Don’t want the top to be the exact element, -100 will go to the top for a little bit more
}
});
});
}
};
});

Resources