empty ng-src doesn't update image - angularjs

I am using the ng-src directive in order to avoid the browser to request the image before Angular evaluate the expression.
ng-src={{image}} will update the src attribute of the image if the expression "image" change.
I misunderstand why the ng-src directive doesn't update the path of the image if the expression ("myImage.png") become empty ("").
When the expression become empty, the ng-src attribute become empty but the src attribute still the last known src. So it doesn't update the image. Why the src attribute isn't updated (to an empty src) so that the image "disappear".
Here is a plunker
Thanks

The answer to this is in the Angular code. It's not a bug, it's just the behavior they decided they wanted. Starting on line 13895, you can see this directive code:
forEach(['src', 'srcset', 'href'], function(attrName) {
var normalized = directiveNormalize('ng-' + attrName);
ngAttributeAliasDirectives[normalized] = function() {
return {
priority: 99, // it needs to run after the attributes are interpolated
link: function(scope, element, attr) {
attr.$observe(normalized, function(value) {
if (!value)
return;
attr.$set(attrName, value);
if (msie) element.prop(attrName, attr[attrName]);
});
}
};
};
});
The key is in:
if (!value) return;
So as you can see, if you change the ng-src expression to an empty string, this will never change the actual src value. You can get around this doing something MadScone suggested.

MadScone's suggestion is a cool idea, but it didn't work for me in all browsers. I ended up just showing the element only when the src isn't empty:
<img ng-show="theImage!==''" ng-src="{{theImage}}">
This seems like the safest option to me after reading through the thread that MadScone referenced (here). As a number of people pointed out there, the accepted answer doesn't work in all browsers and has some other issues that could arise. Simply hiding the element avoids all that.
Update:
As enpenax pointed out in the comments, the !=='' in the ng-show is totally unnecessary. Here's the cleaner version:
<img ng-show="theImage" ng-src="{{theImage}}">

Update (April 2015)
See developering's answer, apparently this method I suggested originally may not work in all browsers.
Original (February 2014)
I'm not fully sure why that's happening, but here's a way of solving it anyway. Add this function to your controller:
$scope.getImage = function(src) {
if (src !== "") {
return src;
} else {
return "//:0";
}
};
The "blank" image will get a source of //:0 which won't cause a missing image icon to appear (see the top answer on this thread).
Then you can set your source using:
<img ng-src="{{getImage(superImage)}}" />
EDIT:
Actually, it would be easier to change your button click to this:
<button ng-click="superImage = '//:0'">Remove superImage</button>
Then there's no need for the function. Although I think the function method is better.

Another short way of solving it:
<img ng-src="{{image?image:' '}}" />

fix it by set value = " ";
with whitespace.
I also add the following css to make sure it's not displayed.
img[src="_"]
display none !important
the real reason has been discussed here: https://github.com/angular/angular.js/issues/1218

ng-hide and ng-show can help you solve it
<img ng-src="{{Image}}" ng-hide="Image == null" ng-show="Image != null" ng-click="ChooseImage()" width="100%" />
$scope.Image = null;
or
<img ng-src="{{Image}}" ng-hide="Image === ''" ng-show="Image !== ''" ng-click="ChooseImage()" width="100%" />
$scope.Image = '';

<img data-ng-src="{{image || 'http://www.1x1px.me/FFFFFF-0.png'}}" data-ng-model="image">
You can choose any 1x1px image that suitable to your website and replace http://www.1x1px.me/FFFFFF-0.png of your own. For my website I use available image on http://www.1x1px.me.
P/S: No need to worry about the original src attribute of img tag because it's not affected to image model

A possible workaround to empty ng-src can be found here.
<img ng-src="{{image || '//:0' }}" />
Detailed explanation to use //:0 can be found from this answer.
To summarize:
It adopts the current protocol, omits the hostname and sets the port to zero, which is invalid and should be killed by the network layer.
Also instead of emptying ng-src, if you have a default image source then you can simply set the ng-src to that default src when ng-src have to be empty.

<img src="{{superImage}}" />
This works as expected
Edit:
Other work arround,may be you could have used and empty string.
ng-click="superImage = ' '
to make it empty. It does not trigger 404

Related

How to test text-overflow element

when the text attribute is set to
text-overflow: ellipsis;
the overflowed text will be displayed as "XX..." (see screenshot for more )
how can I find the overflowed text/element in webdriver?
thanks in advance
Screenshot of Overflowed text
Probably the easiest/best way to do this is to use the JS innerText property, e.g.
driver.findElement(lcoator).getAttribute("innerText");
If I remember correctly, some browsers use textContent instead.
driver.findElement(lcoator).getAttribute("textContent");
This should get you the full text inside that element.
You could also pull innerHTML and parse it (if needed) or remove the text-overflow style from the element but these are harder/more complicated.
In case you have jQuery available in your project, you can write your own selector:
$.expr[':'].truncated = function (e) {
// you *might* want to check if css property "text-overflow"
// is set to "ellipsis" as well, to filter other truncations:
return e.offsetWidth < e.scrollWidth;
};
and go from there:
items = $('.your-selector:truncated');
(heavily based on the answers here)

Show button if two values are equal

I'm finishing up an app of mine, which is a forum, and I need users to be able to delete their own topics.
So, In my "Topics List" template, I have successfully rendered the following code:
<body ng-app>
[...]
<button ng-show="estudante == 'admin'"></button>
[...]
From:
<button ng-show="{{ request.user.username }}=='{{ topic.creator }}'">Remover Tópico</button>
This button should not be displayed if the values of topic.creator and request.user.username are not equal. However, ng-if, ng-hide and ng-show properly configured don't seem to have any effect.
Is there a way to get this to work? Am I missing something on the scopes topic? :)
Thanks in advance!
UPDATE:
Using '' in both values or none is the same. The button is displayed if the value mismatches:
Forum
Normally you dont need the curly brackets around the variable like {{xxx}} in this case. And also the '' can be removed, maybe it works after removing them.
<button ng-show="request.user.username == topic.creator">Remover Tópico</button>
Try this:
<button ng-show="request.user.username == topic.creator">Remover Tópico</button>
In your controller you should have the values you wish to compare assigned to $scope something like this:
$scope.request.user.username = "some name";
$scope.topic.creator = "some name";
<button ng-show="reqeust.user.role === 'admin' && user.username === topic.crator">Remover Tópico</button>
i think this solve this problemn, but verify your code.

Image ng-Src with dependancy

I have an image on my page like so:
<img ng-src='http://someurl.com/image.png?parameter={{selected.id}}' />
Is there any way in Angular to prevent ng-src resolution until after {{selected.id}} is set? Basically i do not want to load image until selected.id is set. To set selected.id I need to make Ajax call. What I am experiencing is two calls for the image.
First one with url like so http://someurl.com/image.png?parameter=
Then the second (correct) call after selected.id is set
It seems that this should be easy to do but I cannot think of a way.
Thank You,
Victor
You can use ng-if so the img tag will actually be removed until selected.id is truthy. This means the request for the image won't be made until selected.id is set.
<img ng-src='http://someurl.com/image.png?parameter={{selected.id}}' ng-if="selected.id" />
You can use ng-show directive
<img ng-src='http://someurl.com/image.png?parameter={{selected.id}}'
ng-if="selected.id" />
You can find some demo here :http://jsbin.com/fatote/5/edit?html,js,output

ng-click not setting $location.path() when path is dynamic

I'm trying to use a tag like this:
<a ng-click="$location.path('/restaurant/{{restaurant._id}}')">{{restaurant.name}}</a>
However, nothing happens when I click the tag.
Oddly, if I hard-code the value there, like this:
<a ng-click="$location.path('/restaurant/512ad624b67fe1f446709331')">{{restaurant.name}}</a>
it works as expected.
Screenshot of the DOM:
Why would this be? How could I work around this?
From AngularJS ng-click not invoked with {{$index}} used, you are able to use the variable directly, without braces.
I.e.
<a ng-click="$location.path('/restaurant/' + restaurant._id)">{{restaurant.name}}</a>
Hope this helps!
$scope.doTheNeedful = function(country){
var newPath = "home/";
newPath += country;
$location.path(newPath);
}

jquery checkbox attr change seems not to work

Does anyone have any idea why this code seems not to work?
What am I doing wrong?
JQuery 1.5.1 is used.
JS code:
$('#search_filters #discipline a').click(function(){
var checkbox = $(this).next(':checkbox');
if (checkbox.attr('checked')) {
checkbox.attr("checked", true);
} else {
checkbox.attr("checked", false);
}
$(this).children('img').toggleClass("active");
return false;
});
HTML:
<li>
<a href="#">
<img class="inactive" alt="Football" src="/images/disciplines/e9bc7681813110c/thumb.png">
</a>
<input type="checkbox" name="search_discipline[7]" value="1" class="search_discipline">
</li>
I just ran into this myself. It seems in jQuery 1.5.1 and 1.5.2 setting the checked attribute is a bit buggy. I had better luck with $(':checkbox').val(boolean) (which is even a bit easier).
Update: after some digging, it seems the webkit inspector doesn't actually show the checked attribute in the DOM, but jQuery reads/writes it properly. Very odd. Serves me right for using the nightly webkit builds for dev.
The value of a "checked" attribute should be "checked":
if (checkbox.is(':checked'))
{
checkbox.attr("checked", "checked");
} else {
checkbox.removeAttr("checked");
}
Just two helpful ideas to check the change for attributes:
Write the plain HTML first, without Javascript. Did it work? If so, then write it with JS
If you had modified an html tag recall the attribute itself, so you can check that your code had been executed well. E. g. alert($({your target object}).attr({the attribute which added}));
That's what I do in the most cases.
Some pointers:
$('#search_filters #discipline a') will be selecting all a elements that descend from #discipline that descend from #search_filters. Is this what you indend?
Are you remembering that .next() returns a sibling.
What happens if you remove the href='#'?
Does your click event even fire?

Resources