Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.

Join them; it only takes a minute:

Sign up
Join the Stack Overflow community to:
  1. Ask programming questions
  2. Answer and help your peers
  3. Get recognized for your expertise

I'm quite new to Angularjs and Typescript.

I'll try to keep things short here:

The directive (directives/BikeDirective.ts):

class BikeDirective {
    constructor() {
        var directive: ng.IDirective = {};
        directive.restrict = "E";
        directive.scope = {
            move: "="
        };
        directive.template = '<div>The bike</div>';
        directive.link = (scope, element, attrs: any) => {
            element.on('click', (e) => {
                scope.move('moving!');
            });
        }
        return directive;
    }
}
export = BikeDirective;

The Controller (controllers/MyController):

class MyController {
    whatever: string;
    constructor(public scope) {
        this.whatever = "Whatever";
        scope.vm = this;
    }
    onMove(msg: string) {
        console.log(this.whatever);
    }
}
export = MyController;

The HTML:

    <div ng-controller="myController">
        <my-bike move="vm.onMove"></my-bike>
        <my-bike move="vm.onMove"></my-bike>
    </div>

app.ts

import MyController = require("controllers/MyController");
import BikeDirective = require("directives/BikeDirective");

class app {
    constructor() {
        var app = angular.module('app', [])
            .controller('myController', ['$scope', MyController])
            .directive('myBike', [BikeDirective]);
    }
}
export = app;

main.ts

require.config({
    baseUrl: '.',
    paths: {
        jquery: './Scripts/jquery-2.1.0',
        angular: './Scripts/angular'
    },
    shim: {
        'angular': {
            exports: 'angular'
        }
    }
}); 
require(['app','angular','jquery'], (app, angular, $) => {
    new app;
    angular.bootstrap(document.body, ['app']);
});

I hope the above code is self explanatory. Basically, what I want to do is when clicking on one of the bikes (my-bike directive) the MyController.onMove() function is run. That all works fine. The only problem I am having is that when onMove is executed console.log(this.whatever) outputs undefined, shouldn't it output the string "whatever"? Seems like the scope of MyController is not available in the onMove() stub.

I tried this in plain Angularjs (without TypeScript) and it works fine, am I missing something.

Has anybody experienced this before?

I followed .vm technique used by Basarat in this video: http://www.youtube.com/watch?v=WdtVn_8K17E

Thanks

share|improve this question
up vote 2 down vote accepted

Issue

The issue is in move="vm.onMove" you are passing a reference to a function into the directive i.e.

        directive.scope = {
            move: "="
        };

Calling a reference to a function disconnects it from this.

Quick fix:

onMove = (msg: string) => {
    console.log(this.whatever); //OKAY
}

This explains this a bit more: https://www.youtube.com/watch?v=tvocUcbCupA&hd=1

Better fix:

Don't pass functions into directives i.e. don't use = with functions. Instead use & i.e.

        directive.scope = {
            move: "&"
        };

And then call it from your html i.e. <my-bike move="vm.onMove()"></my-bike>. Calling a function with vm. i.e. vm.onMove() ensures that this is correct inside the function.

Also not related to this issue

element.on callback is not called in the angular context ... so you might want to wrap the callback it in a $scope.$apply

share|improve this answer
    
Thanks @basarat. That works perfectly. I initially did set the scope as "&", that was me experimenting with it. Your answer is great, but I don't have enough reputation points to mark it as the answer – ZeroOne Jun 26 '14 at 6:56
    
@ZeroOne you cannot vote up/down answers at the beginning rep .. but you should always be able to mark as answer if you asked the question : stackoverflow.com/help/someone-answers – basarat Jun 26 '14 at 7:37
    
@ZeroOne thanks mate! – basarat Jun 26 '14 at 11:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.