suMi
suMi

Reputation: 1546

sharing data between angular directive, service and controller

I have a setup where I am using a service to send data to a proxy server. It looks like this:

    angular.module('app').service('apiService', ApiService);

function ApiService($http) {
    this.$http = $http;
};

ApiService.prototype.uploadFile = function(fileContent) {
    $.ajax({
        url: "/space_uploadFile/",
        type: "POST",
        dataType: "json",
        data: {
            fileContent: fileContent
        },

        contentType: "application/json",
        cache: false,
        timeout: 5000,
        complete: function() {
          //called when complete
          console.log('process complete');
        },
        success: function(data) {
          console.log(data);
          console.log('process success');
       },
        error: function() {
          console.log('process error');
        },
      });
};

next I am calling a directive that handles file loading and cropping of the image

use strict';
angular
    .module('app')
    /**
    * The ng-thumb directive
    * @author: nerv
    * @version: 0.1.2, 2014-01-09
    */
    .directive('ngThumb', ['$window', 'apiService', function($window, apiService) {
        var helper = {
            support: !!($window.FileReader && $window.CanvasRenderingContext2D),
            isFile: function(item) {
                return angular.isObject(item) && item instanceof $window.File;
            },
            isImage: function(file) {
                var type =  '|' + file.type.slice(file.type.lastIndexOf('/') + 1) + '|';
                return '|jpg|png|jpeg|bmp|gif|'.indexOf(type) !== -1;
            }
        };

        return {
            restrict: 'A',
            template: '<canvas/>',
            link: function(scope, element, attributes) {
                if (!helper.support) return;

                var params = scope.$eval(attributes.ngThumb);

                if (!helper.isFile(params.file)) return;
                if (!helper.isImage(params.file)) return;

                var canvas = element.find('canvas');
                var reader = new FileReader();

                reader.onload = onLoadFile;
                reader.readAsDataURL(params.file);


                function onLoadFile(event) {
                    var img = new Image();
                    img.onload = onLoadImage;
                    img.src = event.target.result;
                }
                function uploadFile(imageData){
                    var self = this;
                    apiService.uploadFile(imageData);
                }

                function onLoadImage() {
                    var width, height;
                    if (params.height>params.width) {
                        width=params.width*3;
                        height=width;
                    } else {
                        height = params.height*3;
                        width=height;
                    }
                    var maxWidth=600;
                    if (width<maxWidth) {   
                        maxWidth=width;
                    }
                    //width = params.width || this.width / this.height * params.height;

                    canvas.attr({ width: width, height: height });
                    canvas[0].getContext('2d').drawImage(this, 0, 0, maxWidth, maxWidth, 0,0, width, height);
                    //canvas[0].getContext('2d').drawImage(this, 0, 0, width, height);
                    var image = canvas[0].toDataURL();
                    uploadFile(image);
                }
            }
        };
    }]);

now I would need the data returned by the Ajax request (data variable) to be passed to my controller

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


function newProjectController($rootScope, $scope, $location, apiService, FileUploader) {
    this.apiService = apiService;
    /*$scope.encoded = $base64.encode('a string');
    console.log($scope.encoded);
    $scope.decoded = $base64.decode('YSBzdHJpbmc=');*/
    $rootScope.img="";

    var uploader = $scope.uploader = new FileUploader({
            url: '/space_uploadFile'
        });

        // FILTERS

        uploader.filters.push({
            name: 'imageFilter',
            fn: function(item /*{File|FileLikeObject}*/, options) {
                var type = '|' + item.type.slice(item.type.lastIndexOf('/') + 1) + '|';
                return '|jpg|png|jpeg|bmp|gif|'.indexOf(type) !== -1;
            }
        });
} 

I cannot figure a way to either inject my $rootScope to the service or return data from the Ajax request to the directive. For other uploads I'm using $http.get(...) but I couldn't figure out how to do that using the json-encoded base64 image.

Can someone give me a hint? thanks already!

UPDATE 1. I've tried with Daniels suggestion. My watch looks like this

$scope.file=apiService.file;

        $scope.$watch("apiService.file", function (newVal, oldVal, scope) {
            console.log(newVal);
            console.log("update");
        });

The problem is it gets called onload but not when the variable is updated... What's wrong here?

Upvotes: 1

Views: 129

Answers (1)

Amygdaloideum
Amygdaloideum

Reputation: 4913

You can store the response in the service and then access it in the controller by injecting the service to it. You can put a watcher on the file variable to know when it has changed.

function ApiService($http) {
  this.$http = $http;
  this.file = {};
};

ApiService.prototype.uploadFile = function(fileContent) {
  $.ajax({
    //...
    success: function(data) {
      this.file = data;
    }
  //...
  });
};

Another option would be to send the responsedata to your controller using a $rootscope.$broadcast() event.

Upvotes: 2

Related Questions