最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Correct way of wrapping javascript class in AngularJS module and inject angular services - Stack Overflow

programmeradmin6浏览0评论

Inside an AngularJS module I'm developing, I have a Canvas class defined as:

angular.module("myModule", [])
.factory("Canvas", function() {return Canvas;});

var Canvas = function(element, options) {
    this.width = options.width || 300;
    this.height = options.height || 150;
    this.HTMLCanvas = $(element).get(0);
    this.HTMLCanvas.width = canvas.width;
    this.HTMLCanvas.height = canvas.height;
    this.objects = [];
    //Initialize canvas
    this.init();
}
Canvas.prototype.init = function() {/*...*/};
Canvas.prototype.otherMethod = function() {/*...*/};

Now, the Canvas class is never instantiated from inside the module, but rather from an AngularJS controller, like so:

angular.module("myApp.controllers", ["myModule"])
.controller("MainCtrl", ["Canvas", function(Canvas) {
    var canvas = new Canvas("#canvas", {/*options object*/});
    //...
}]);

And so far everything works like a charm. But then I realized that I need the $q service in my canvas object, and since I don't want to resort to injecting it into my controller and then passing it to the Canvas constructor, I thought of modifying my module like so:

angular.module("myModule", [])
.factory("Canvas", ["$q", function(q) {
    var that = this;
    that.q = q;
    return function() {
        Canvas.apply(that, arguments);
    };
}]);

var Canvas = function(element, options) {
    console.log(this.q, element, options);
    this.width = options.width || 300;
    this.height = options.height || 150;
    this.HTMLCanvas = $(element).get(0);
    this.HTMLCanvas.width = canvas.width;
    this.HTMLCanvas.height = canvas.height;
    this.objects = [];
    //Initialize canvas
    this.init();
}
Canvas.prototype.init = function() {/*...*/};
Canvas.prototype.otherMethod = function() {/*...*/};

The initial console.log correctly logs the $q service and the Canvas's original arguments, element and options, but breaks on the call to its init method:

TypeError: undefined is not a function

I suppose that's because this is no longer an instance of Canvas but rather of the anonymous function function(q) {...}.
Any hints on how I can instantiate new Canvas objects with the q property and still retain the class's methods?

EDIT

I've modified my code slightly to give a better idea of what I'd like to achieve:

angular.module("myModule", [])
//.factory("Canvas", function() {return Canvas;})
//.factory("Canvas", ["$q", CanvasFactory])

function CanvasFactory(q) {
    var canvas = this;
    canvas.q = q;
    return function() {
        Canvas.apply(canvas, arguments);
    };
}

var Canvas = function(element, options) {
    console.log(this instanceof Canvas, typeof this.q !== "undefined");
};

If I unment the first factory, console.log yields true false, whereas the second factory yields false true. My goal is to get true true, which means that this is in fact an instance of the Canvas class and has the q property defined. Any hint is greatly appreciated.

Inside an AngularJS module I'm developing, I have a Canvas class defined as:

angular.module("myModule", [])
.factory("Canvas", function() {return Canvas;});

var Canvas = function(element, options) {
    this.width = options.width || 300;
    this.height = options.height || 150;
    this.HTMLCanvas = $(element).get(0);
    this.HTMLCanvas.width = canvas.width;
    this.HTMLCanvas.height = canvas.height;
    this.objects = [];
    //Initialize canvas
    this.init();
}
Canvas.prototype.init = function() {/*...*/};
Canvas.prototype.otherMethod = function() {/*...*/};

Now, the Canvas class is never instantiated from inside the module, but rather from an AngularJS controller, like so:

angular.module("myApp.controllers", ["myModule"])
.controller("MainCtrl", ["Canvas", function(Canvas) {
    var canvas = new Canvas("#canvas", {/*options object*/});
    //...
}]);

And so far everything works like a charm. But then I realized that I need the $q service in my canvas object, and since I don't want to resort to injecting it into my controller and then passing it to the Canvas constructor, I thought of modifying my module like so:

angular.module("myModule", [])
.factory("Canvas", ["$q", function(q) {
    var that = this;
    that.q = q;
    return function() {
        Canvas.apply(that, arguments);
    };
}]);

var Canvas = function(element, options) {
    console.log(this.q, element, options);
    this.width = options.width || 300;
    this.height = options.height || 150;
    this.HTMLCanvas = $(element).get(0);
    this.HTMLCanvas.width = canvas.width;
    this.HTMLCanvas.height = canvas.height;
    this.objects = [];
    //Initialize canvas
    this.init();
}
Canvas.prototype.init = function() {/*...*/};
Canvas.prototype.otherMethod = function() {/*...*/};

The initial console.log correctly logs the $q service and the Canvas's original arguments, element and options, but breaks on the call to its init method:

TypeError: undefined is not a function

I suppose that's because this is no longer an instance of Canvas but rather of the anonymous function function(q) {...}.
Any hints on how I can instantiate new Canvas objects with the q property and still retain the class's methods?

EDIT

I've modified my code slightly to give a better idea of what I'd like to achieve:

angular.module("myModule", [])
//.factory("Canvas", function() {return Canvas;})
//.factory("Canvas", ["$q", CanvasFactory])

function CanvasFactory(q) {
    var canvas = this;
    canvas.q = q;
    return function() {
        Canvas.apply(canvas, arguments);
    };
}

var Canvas = function(element, options) {
    console.log(this instanceof Canvas, typeof this.q !== "undefined");
};

If I unment the first factory, console.log yields true false, whereas the second factory yields false true. My goal is to get true true, which means that this is in fact an instance of the Canvas class and has the q property defined. Any hint is greatly appreciated.

Share Improve this question edited Aug 30, 2014 at 16:33 Andrea Aloi asked Aug 30, 2014 at 15:39 Andrea AloiAndrea Aloi 9911 gold badge17 silver badges38 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 5

I figured it out:

angular.module("myModule", [])
.factory("Canvas", ["$q", function(q) {
    Canvas.prototype.q = q;
    return Canvas;
}]);

var Canvas = function(element, options) {
    console.log(this instanceof Canvas, typeof this.q !== "undefined");
};

This logs: true true.

I create Canvas service like this and is work:

var app = angular.module('myModule', []);

app.factory("Canvas", ["$q", function($q) {

    var Canvas = function(element, options) {
        this.q = $q;

        this.init();
        console.log(this.q, element, options);
    }
    Canvas.prototype.init = function() {/*...*/};
    Canvas.prototype.otherMethod = function() {/*...*/};

    return Canvas;
}]);

app.controller('MainCtrl', ['$scope', 'Canvas', function($scope, Canvas) {
    console.log( new Canvas().q );  
}]);

Also you can see this on Pluncer here

发布评论

评论列表(0)

  1. 暂无评论