0

I created a custom directive whose purpose is to dynamically assign a base64 string and file extension as a background image to a <div> which will be used as a user profile photo. Here is the relevant code:

app.directive('backImg', function() {
    return {
        link: function(scope, element, attrs) {
            scope.$watchGroup(['profilePictureStr', 'profilePictureExt'],
            function(newValues, oldValues, scope) {
                element.css({
                    'background-image': 'url(data:image/' +
                                        scope.profilePictureExt + ';base64,' +
                                        scope.profilePictureStr + ')',
                    'background-size':'contain',
                    'background-repeat':'no-repeat',
                    'background-position':'center'
                });
            });
        }
    };
});

here is the <div> whose CSS I would like to dynamically control from the directive:

<div back-img>

What I currently observe is that the first time the watch gets called, upon load, the element.css() call succeeds. However, at page load the scope variables profilePictureStr and profilePictureExt have not yet been assigned, and are empty string. Shortly thereafter, the page makes a REST call to retrieve the base-64 image string corresponding to the logged in user. However, the second time the watch is called, the element.css() call does not appear to stick. The code does in fact get called, but the CSS seems to be unchanged.

Is it not possible to dynamically change CSS in the DOM from an Angular directive more than once? At this point I am leaning towards just putting everything into the style attribute of the <div> in question, but I would much rather use a directive to do this if possible.

2
  • Have you tried adding a conditional in the $watch callback to check that the two scope variables aren't ''? Then the next time element.css is called it will be with the correct values. Commented Dec 15, 2016 at 9:06
  • @Ankh The scope variables have the correct value during the second call, I verified that. Commented Dec 15, 2016 at 9:09

2 Answers 2

1

try this

app.directive('backImg', function() {
        return {
            link: function(scope, element, attrs) {
                scope.$watchGroup(['profilePictureStr', 'profilePictureExt'],
                    function(newValues, oldValues, scope) {

                        if (scope.profilePictureExt && scope.profilePictureStr) {

                            element.css({
                                background: 'url("data:image/' + scope.profilePictureExt + ';base64,' + scope.profilePictureStr + '") contain no-repeat center'
                            });


                        }

                    });
            }
        };
    });
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the quick reply. The result I get is very strange. This is what I see in the style attribute of the <div>: style="background-size: contain; background-repeat: no-repeat; background-position: center center;" ... in other words, the background-image attribute does not even appear. Do you have any idea what could be going on here?
I think my data has a problem, maybe the browser can't make the background string assignment. Checking for this now.
can you log here the data object to to see it with ext.
0

It turns out the problem was being caused by passing an incorrectly built url string as the background-image property in my directive. Here is what I was passing:

url(data:image/png;base64,R0lGO...)

If you look closely, you will see that there are no single quotes around the content inside parentheses, which are required. After fixing this problem, the url looked like this:

url('data:image/png;base64,R0lGO...')

While this is just a typo, this question is useful because of the way Angular handled this error. This was a silent error, with no output to the console of any kind. In addition, it appears that the other valid CSS properties were being set, with just the background-image being ignored.

Thanks to @AhmedMostafa for tipping me off in the right direction.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.