2

I'm having trouble retrieving the value of an attribute passed in to a directive. My understanding of how directives work probably has something to do with this but it's my assumption that this is a scope related issue.

If you check the code below you'll see the attribute is being used as such:

display="contest.StyleBgImageMedia.filename" 

This value of contest.StyleBgImageMedia.filename is a string and I've verified it exists by consoling it our from the controller. The problem is that when trying to access it within the directives link function I can't retrieve the value but only the attribute name.

This directive is used in the view like such:

<uploader class="pull-left" action="builder/uploadMediaFile" display="contest.StyleBgImageMedia.filename" data-file="style_bg_image_media_id"></uploader>

The full directive has been posted below. You'll see that I'm using $observe to render the value of the display attribute but this isn't working.

app.directive('uploader', function($rootScope) {
    return {
        restrict: 'E',
        scope: {
            action: '@',
            display: '@display'
        },
        link: function(scope, elem, attrs) {
            elem.find('.fake-uploader').click(function() {
                elem.find('input[type="file"]').click();
            });

            scope.progress = 0;

            attrs.$observe('display', function(value) {
                if (value) {
                    scope.avatar = value;
                }
            });

            scope.sendFile = function(el) {
                var $form = jQuery(el).parents('form');
                if (jQuery(el).val() === '') {
                    return false;
                }

                $form.attr('action', scope.action);
                scope.$apply(function() {
                    scope.progress = 0;
                });

                $form.ajaxSubmit({
                    type: 'POST',
                    uploadProgress: function(event, position, total, percentComplete) {
                        scope.$apply(function() {
                            scope.progress = percentComplete;
                        });
                    },
                    error: function(event, statusText, responseText, form) {
                        $form.removeAttr('action');
                    },
                    success: function(responseText, statusText, xhr, form) {
                        var ar = jQuery(el).val().split('\\'),
                            filename =  ar[ar.length-1];

                        $form.removeAttr('action');
                        scope.$apply(function() {
                            scope.avatar = filename;
                        });

                        var response = jQuery.parseJSON(responseText);
                        $rootScope.$broadcast('file-uploaded', {
                            'model': attrs.file,
                            'file': response.message
                        });
                    }
                });

            };
        },
        replace: false,
        templateUrl: 'builder/views/partials/upload.php'
    };
});

1 Answer 1

3

$observe doesn't work unless the attribute value contains interpolation.

So, you can change the attribute to be:

<uploader display="{{contest.StyleBgImageMedia.filename}}" ...>

Alternatively, you can use watch: scope.$watch('display', ...) with this isolated scope binding:

display: '='
Sign up to request clarification or add additional context in comments.

2 Comments

And you check a good answer here explaining difference between $observe and $watch (stackoverflow.com/a/14907826/1310945)
Great feedback, thanks. I was having trouble understanding the difference between the two.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.