riegersn
riegersn

Reputation: 2849

Why would "this" in function inside angularjs service be undefined

Why would this inside function be undefined in angularjs service?

.service('SliceService', function () {
    var self = this;

    var Slice = function(intervals, intervalSpan) {
        self.activeSlice = [];
        self.hasNext = true;
        self.hasPrevious = false;
        self.intervals = intervals;
        self.intervalSpan = intervalSpan;
    }

    Slice.prototype.findIntervalIndex = function (time, slice) {
        slice = slice || self.intervals;
        return _.findIndex(slice, function (o) {
            return o.time === time;
        });
    };

    return Slice;

})

.controller('myController', ['SliceService', function(SliceService) {
    SliceService([arr], 12);
    SliceService.findINtervalIndex(time);
}])

In the above example when using it in a controller, this.activeSlice throws an error TypeError: Cannot set property 'activeSlice' of undefined.

-

Update

Thanks, everyone! I've updated my example to better reflect what I'm trying to do. With the above I'm getting a TypeError: SliceService.findIntervalIndex is not a function — Also maybe a service is not fit for what I'm trying to do?

Upvotes: 1

Views: 710

Answers (2)

riegersn
riegersn

Reputation: 2849

Thanks to @SeedyROM and some additional google searches on angular services. This solved all my issues...

angular.module('vpower.services').service('SliceService', function () {
    this.activeSlice = [];
    this.hasNext = true;
    this.hasPrevious = false;
    this.intervals = [];
    this.intervalSpan = 12;

    this.findIntervalIndex = function (time, slice) {
        var curTime;
        slice = slice || this.intervals;
        return _.findIndex(slice, function (o) {
                curTime = o.time._i || o.time;
            return curTime === time;
        });
    };

I think I was not fully understanding the way services work.

Upvotes: 0

SeedyROM
SeedyROM

Reputation: 2451

Try saving the value of "this" before accessing it inside the anonymous scope:

(function(){
    'use strict';

    angular.module('myServices').service('SliceService', function () {
        var context = this;

        var Slice = function(intervals, intervalSpan) {
            context.activeSlice = [];
            context.hasNext = true;
            context.hasPrevious = false;
            context.intervals = intervals;
            context.intervalSpan = intervalSpan;
        }

        return Slice;
    });
}());

Using Bind:

    angular.module('myServices').service('SliceService', function () {
        var Slice = function(intervals, intervalSpan) {
            this.activeSlice = [];
            this.hasNext = true;
            this.hasPrevious = false;
            this.intervals = intervals;
            this.intervalSpan = intervalSpan;
        }.bind(this);

        return Slice;
    });

Note: using arrow function of javascript ES6 makes sure that this always points to the same context. so you could replace regular function with arrow function. This is however not universally supported without transpiling.

service('SliceService', ()=>{ 
 // operations
}

Upvotes: 2

Related Questions