angularjs: only set background-image on ngStyle if url is defined - angularjs

I have a property on the scope which can hold an url (bgUrl) of an image. Now I would like to use this image as a background image of a 'div'. However, if the property is undefined I would like to use a default image which is defined by the class bg-image. Now I can do it like
<img ng-show="bgUrl" ng-src="bgUrl"/>
<div ng-hide="bgUrl" class="bg-image"/>
However, I would like to combine this into one element. I tried something like this
<div class="gb-image" ng-style="{true: 'background-image': 'url(\'' + bgUrl + '\')'}[bgUrl]"/>
I just copied some code from google (no idea if this can ever work). One thing is clear though, this doesn't work :)
What would be a nice angular way to solve this and can my solution work ?

Right way is a directive way:
app.directive('bg', function () {
return {
link: function(scope, element, attrs) {
if(scope.bgUrl){
element.css("background-image","url("+scope.bgUrl+")");
} else {
element.addClass("bg-default");
}
}
}
});
Take a look: http://plnkr.co/edit/xYEjpp?p=preview

Related

If ngSrc path is empty or gives 404 error, how to replace it with a string

I am reading a file that contains an image path. This image path could be empty or wrong. So in case of error, I would like to replace the image with a string, not with another image.
I used a little trick, but I would like to know if it is correct or there is a better way to do it.
This is the snippet of the HTML/Angular code:
<h1><img ng-src="{{component.img || 'none'}}" err-src><span>{{component.title}}</span></h1>
This is the directive I have created:
myApp.directive('errSrc', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('error', function() {
element.parent().addClass("no-image");
});
}
};
});
Initially, img is visible and span is not. Of course in the CSS file i have create a class h1.no-image that will display the span and hide the img.
Does anyone know a better way or "more Angular"-like way to realize this feature? Thanks
http://makandracards.com/makandra/29415-resolving-angular-not-updating-an-image-src-when-ng-src-is-empty
ng-src="{{component.img || '//:0'}}"
http://plnkr.co/edit/XmyLCpwJTodBrMrW2QHZ?p=preview
Try below line :
<img ng-src="(component.img === undefined) ? 'none' : component.img" err-src>
May be you can use 2 img tags:
<img ng-src="{{url}}" ng-if="url_correct"/>
<img src="url_to_default_picture" ng-if="!url_correct"/>
So ng-if will insert only one tag in result html

change Background image in directive

i want to load an image as background in the directive. This should happen after an event. For example if the flag is true, the background should be changed.
How is it possible?
myApp.directive('imgDir', function () {
return {
restrict: 'A',
scope: {
updateMethod: '=',
},
link: function (scope, element, attrs) {
this.changeBackground = function(flag){
if(flag){
var url = '/images/pic1.jpg'
//load pic1 as background
}
else{
var url = '/images/pic2.jpg'
//load pic2 as background
}...
});
How does the html have to look like? Because the url is defined in the directive.
thx
If you just need to change image you can use ng-class and some css rules. https://docs.angularjs.org/api/ng/directive/ngClass
<div ng-class="{'img-1':flag, 'img-2':!flag}"></div>
and in your css
.img-1 {
background-image: url('/images/pic1.jpg');
}
.img-2 {
background-image: url('/images/pic2.jpg');
}
At a first glance i'm not even sure your directive would work. If you want to know more about directives and how to make one you should read this: https://docs.angularjs.org/guide/directive
the HTML should be like
<div img-dir updateMethod="...">
...
</div>
,following the online official documentation. A directive restricted as attribute is written in the opening tag and if the scope specifies another attribute, it can be added inline.

How to not refer to the controllerAs name in directive

Here is the minimal code to describe the issue. On the page, I have:
<div ng-controller='AController as a'>
<div a-directive></div>
</div>
In js, I have:
app.directive("aDirective", function($compile){
return {
scope: true,
link: function(scope, element, attrs) {
var template = "<h1>{{a.label}}</h1>";
element.append($compile(template)(scope));
}
}
});
app.controller("AController", function($scope){
self = this;
self.label = "some text";
});
That works, but the issue is that {{a.label}}, which made the view and controller/model tightly coupled. Is there any way to get rid of that a., and not to mention the controllerAs-name in the directive code at all? (just like what I did in the controller code)
To improve this you can pass the text to display as a parameter to the directive. Something like this is the initial idea:
<div a-directive="a.label"></div>
However, I DO recommend using an alias for the controller, so I made a Plunker where you can see all of this working together with some improvements.
Check it out here: http://plnkr.co/edit/1hBSBxwSEPXoj9TULzRQ?p=preview
I would also recommend to use template instead of link and restricting the directive to an element instead of using it as attribute, since it is modifying the DOM. But yeah, you could keep improving it till the end of the times :)

TextAngular is not functioning as expected?

I just shifted from summernote to angularText. With summernote as my html editor everything was working as expected.
With angularText my editor shows fine, and the html previously entered (under summernote) looks fine. But there is a MAJOR issue!
If I type a single key into the editor, all the html tags VANISH.
One might imagine that I am missing something in the setup, but the initial display looks fine. It is only after I enter a key that things radically change. In order to keep things simple I have in my scope:
$scope.html = "<p>Hello There</p>";
and the relevant markup is:
<div text-angular ng-model="html"></div>
<textarea ng-model="html" style="width: 100%"></textarea>
Before the key stroke I see:
After the key stroke all the html tags are GONE!
You help is greatly appreciated!
PS: 'Dumb is really powerful!' and I am probably missing something obvious!
It turns out that I had a directive: contenteditable that was causing havoc with textAngular. I renamed my directive and the issue was immediately solved.
As it turns out I really need this contenteditable directive in other places! The final solution as quite reasonable. In my contenteditable directive, I simply tested for the class names for those contenteditible elements, and stopped the directive from modifying the html otherwise. Hence I added within my contenteditable directive:
link: function (scope, element, attrs, ngModel) {
...
...
if (!element.hasClass('task_name')) {
// don't affect any elements which don't have 'task_name' class
// so don't bind or $render
}
else
{
ngModel.$render = function () {
element.html(ngModel.$viewValue || "");
};
element.bind("blur keyup change", function () {
// read is my magic needed for the task_name elements
scope.$apply(read);
});
}
}

override angular ui-router for links to page anchors

I have links to anchors on my page (a href="#idea"). ui-router obviously overrides them. Is there a way to use both in harmony? Thank you.
https://gist.github.com/anonymous/2880f2f2c9f91b0b695f#file-gistfile1-txt
Well you aren't supposed to use it on a href this way, instead you should add it like the following:
...
You can see an example of this at the bottom of the $anchorScroll API here.
If you want to combine ui-router with anchor tag, I solved my problem using this code
<a ui-sref="routename({'#': 'ownerfeatures'})">Link</a>
Hi I had similar problem with anchors.
Since I want to go on using regular HTML syntax (href="#may-hash") I've made a directive which looks if a link is an anchor and if yes perform scroll operations. See detailed code :
/**
* Ressource : https://docs.angularjs.org/api/ng/service/$anchorScroll
*/
.directive('a', ['$location', '$anchorScroll', function ($location, $anchorScroll) {
return {
restrict: 'E',
link: function (scope, elem, attrs)
{
// href should be defined and not empty
if(typeof attrs.href!=='undefined' && attrs.href.length > 0)
{
// href should be an anchor
if(attrs.href.substring(0, 1) === '#')
{
elem.on('click', function (e)
{
// if current hash is different from requested hash
// then set new hash
// no need to call $anchorScroll()
// since scroll is auto if you've not used $anchorScroll.disableAutoScrolling()
if ( '#' + $location.hash() !== attrs.href)
{
$location.hash(attrs.href);
}
// if hash is the same, force scroll
else
{
$anchorScroll();
}
});
}
}
}
};
}])
Better way to do this is this way
say you are on state app.state1.child and your anchor tag is #list, so say that you a tag use this code
<a ui-sref="app.state1.child#list">Link</a>
I know is an old topic but always get stuck looking a better solution to do the anchoring in my apps.
Today I was looking to scroll in the same page and tested a lot of differents solutions. Most of the time this one is the general recommendation:
<a ui-sref="routename({'#': 'ownerfeatures'})">Link</a>
The problem with this one is works to transition to a new state and go to the anchor but doesn't work well if you want to just scroll in the same page, because it only works the first click.
Then I realize that the use of $anchorScroll should be great for this and I made this directive maybe can help someone. Note I didn't use location.hash, because I don't want to add the hash to my address bar and also there where some situations in my flow that make the screen scroll when not required.
function anchorScroll($anchorScroll){
return {
restrict: 'A',
scope: {
target: '=anchorScroll'
},
link: function ( scope, element, attrs ) {
element.bind('click', function(event) {
console.log(scope.target)
$anchorScroll(scope.target);
})
}
}
}
But the also there is a very simplest way, just using $anchorScroll in the template. In your controller:
$scope.anchorScroll = $anchorScroll;
And in the view:
Scroll to ID

Resources