Jwqq Jwqq - 25 days ago 8
AngularJS Question

How to pass data from directive to parent scope in my case?

I have a question regarding the directive and controller.

I want to pass the data from directive to controller in my case.

template html

<img ng-src=“{{url}}” image-detect />

<div>width: {{width of image}}</div> // how do I show the value here
<div>height: {{height of image}}</div>


directive

(function () {
angular
.module(‘myApp’)
.directive(‘imageDetect’, imageDetect);

function imageDetect() {
var directive = {
'restrict': 'A',
'controller': imageController
};

return directive;
}

function imageController($scope, $element) {
$element.on('load', function() {
$scope.imageWidth = $(this).width();
$scope.imageHeight = $(this).height();

//not sure what to do to pass the width and height I calculate in directive to the parent
});
}
})();


How do I pass
imageWidth
and
imageHeight
to the parent scope and show it in the template? Thanks a lot!

Answer

Two methods come to my mind:

  1. You can have an object something like imageDimention declared on base/parent/whatever scope and then have it shared with directive through scope isolation and then from directive's controller's scope you can access that imageDimention object and set its imageWidth and imageHeight properties. Setting these properties in directive will take effect in base/parent/whatever scope as well:

Example of scope isolation, copied from angular documentation

angular
    .module('yourapp')
    .directive('myImage', function() {
      return {
        restrict: 'E',
        scope: {
          imageDimention: '=imageDimention'
        },
        controller: 'ImageController'
      };
    });

Then in ImageController's scope you can access same imageDimention object

  1. Create a ContextService this can be used for sharing data between different angular components not just these image properties. Its good to have a ContextService somewhat generic so that it can be reused/general purpose.

ContextService can be something like:

angular.module('yourapp')
        .factory('ContextService', ContextService);
    function ContextService() {
        var service = {};
        var data = {};
        service.set = set;
        service.get = get;


        function set(key, value) {

            if(key !== null && key !== undefined){
                data[key] = value;
            }

        }

        function get(key) {
            return data[key];
        }

        return service;
    }

And then you can inject this service into your angular components(controllers/directives/other services) and access it as some kind of global objects because services are singleton, this will serve you as data sharing module.

In your case, you probably have a controller that is attached to view, so assuming you have that controller, should declare an object say image on this controllers scope:

$scope.image = {
    url: 'imageUrl'
    width: '0px',
    height: '0px',
}

Then your html template should probably be something like this:

<img ng-src="{{image.url}}" image-detect />

<div>width: {{image.width}}</div>
<div>height: {{image.height}}</div>

And your directive should look like this:

(function () {
     angular
        .module(‘myApp’)
        .directive(‘imageDetect’, imageDetect);

    function imageDetect() {
        var directive = {
            'restrict': 'A',
            'scope': {
                'image': '=image'
            },
            'controller': imageController
        };

        return directive;
    }

    function imageController($scope, $element) {
        $element.on('load', function() {
            //here you can access image object from scope which is same as controller that is attached to the view
            $scope.image.width = $(this).width();
            $scope.image.height = $(this).height();
        });
    }
   })();

I hope this might help...