Mr X
Mr X

Reputation: 1739

How to replace the existing attribute and its value to custom directive and call function in directive

I am using image fallback and made a factory for the same,

Controller

(function () {
    'use strict';

    angular
        .module('app')
        .controller('myCtrl', myCtrl);

    /* @ngInject */
    function myCtrl(GetInitials) {

        var vm = this;

        vm.getInitials = function(name){
            return GetInitials.getInitials(name);
        };

    }
})();

In HTML I am using the image fallback as

<img class="md-avatar" fallback-src="{{vm.getInitials(user.name)}}" ng-src="/assets/images/other/random.jpg"/>

factory

(function() {
    'use strict';

    angular
        .module('app')
        .factory('GetInitials', Service);

    /* @ngInject */
    function Service() {

        var getInitials = function(name) {

            var nameArray = name.split(" ");

            if(nameArray.length > 1){
                name = {
                        first : nameArray[0],
                        last : nameArray[1]
                       };
            } else {
                name = {
                    first : nameArray[0].charAt(0),
                    last : nameArray[0].charAt(1)
                };
            }

            var canvas = document.createElement('canvas');
            canvas.style.display = 'none';
            canvas.width = '45';
            canvas.height = '45';
            document.body.appendChild(canvas);
            var context = canvas.getContext('2d');
            context.fillStyle = "dodgerblue";
            context.fillRect(0, 0, canvas.width, canvas.height);
            context.font = "20px Roboto, 'Helvetica Neue, sans-serif";
            context.fillStyle = "#fff";
            var first, last;
            if (name && name.first && name.first != '') {
                first = name.first[0];
                last = name.last && name.last != '' ? name.last[0] : null;
                if (last) {
                    var initials = first + last;
                    context.fillText(initials.toUpperCase(), 10, 30);
                } else {
                    var initials = first;
                    context.fillText(initials.toUpperCase(), 20, 33);
                }
                var data = canvas.toDataURL();
                document.body.removeChild(canvas);
                return data;
            } else {
                return false;
            }
        };
        return {
            getInitials: getInitials
        };
    }
})();

Instead I want to create a directive for the same so as not to call the factory in every controller and use directive globally. I tried to make some score, called the function and its always throwing error, I am quite stuck how to use directive to replace the image-fallback-initials my-user="User Name" to the original fallback-src="{{vm.getInitials(user.name)}}"

   <img class="md-avatar" image-fallback-initials my-user="User Name" ng-src="/assets/images/other/easde.jpg"/>

Directive for the same

   (function () {
    'use strict';

    angular
        .module('app')
        .directive('imageFallbackInitials', imageFallbackInitials);

    /* @ngInject */
    function imageFallbackInitials() {

        return {
            restrict : "A",
            priority: 200,
            controller: function($scope) {
                // bind myVar property to scope
                $scope.getInitials = function(name) {

                    var nameArray = name.split(" ");

                    if(nameArray.length > 1){
                        name = {
                            first : nameArray[0],
                            last : nameArray[1]
                        };
                    } else {
                        name = {
                            first : nameArray[0].charAt(0),
                            last : nameArray[0].charAt(1)
                        };
                    }

                    var canvas = document.createElement('canvas');
                    canvas.style.display = 'none';
                    canvas.width = '45';
                    canvas.height = '45';
                    document.body.appendChild(canvas);
                    var context = canvas.getContext('2d');
                    context.fillStyle = "dodgerblue";
                    context.fillRect(0, 0, canvas.width, canvas.height);
                    context.font = "20px Roboto, 'Helvetica Neue, sans-serif";
                    context.fillStyle = "#fff";
                    var first, last;
                    if (name && name.first && name.first != '') {
                        first = name.first[0];
                        last = name.last && name.last != '' ? name.last[0] : null;
                        if (last) {
                            var initials = first + last;
                            context.fillText(initials.toUpperCase(), 10, 30);
                        } else {
                            var initials = first;
                            context.fillText(initials.toUpperCase(), 20, 33);
                        }
                        var data = canvas.toDataURL();
                        document.body.removeChild(canvas);
                        return data;
                    } else {
                        return false;
                    }
                };
            },
            link : function(scope,elements,attrs){

               attrs.$set('fallback-src', scope.getInitials(attrs.myUser));
            }
        }
    }
})();

Edited : Update the directive and it working fine.

Here I am getting the fallback-src however its not displaying the name initials,

On doing console check

Here I am getting ng-src, fallback-src and then src

With using factory the sequence is fallback-src ng-src and then src

So the fallback-src is getting updated but its not updating the src and src remains the old one

Upvotes: 0

Views: 45

Answers (2)

Mr X
Mr X

Reputation: 1739

Have worked on the complete solution to create a

Directive For Image Fallback With Name Initials | AngularJs

Complete end to end working code is here:

How to update the src with new fallback-src using the directive?

Few more answers are also provide by other that are good to go with another approach.

Upvotes: 0

MarkoCen
MarkoCen

Reputation: 2334

You mis-matched the order of link function arguments. The arguments passed into directive link function are scope, elements and attrs, so the link function should be

link : function(scope,elements,attrs){
    console.log(attrs.myUser);
}

If you want to register watchers in scope, you should use scope option in directive definition

return {
    restrict : "A",
    scope: {
        myUser: '@'
    },
    link : function(scope,elements,attrs){
        console.log(scope.myUser);
    }
}

Upvotes: 1

Related Questions