0

Given following common setup:

CtrlA (page level controller)
  |- directiveAA (component e.g. button bar)
    |- directiveAAA (sub-component e.g. button)

I would like to call CtrlA.methodA() from directiveAAA by passing the methodA down the chain using directive attributes - CtrlA -> directiveAA -> directiveAAA. So for example my directiveAAA "Save" button can call controller method "Save". Components directiveAA and directiveAAA are dumb components and only know about their environment given their attribute settings.

Before Typescript I would make use of inherited scope down the chain to call controller method $scope.save() from directiveAAA.

How would this work with Typescript? Would we still have to make use of injected scope into our controller, directive controller classes or can this be done without using scope, based on class inheritance?

So here's my question in code - its probably not perfect but gives the gist - the nub of the problem is marked with comment "this is where i need help":

module app.page {

    class CtrlPage {
        private ctrlPageBtnActions: string[] = ['goPrev', 'goNext'];
        goPrev(){
            console.log('go previous');
        }
        goNext(){
            console.log('go next');
        }
    }

    function pageDirective(){
        return {
            restrict: 'E',
            replace: true,
            template: '<button-bar actions="CtrlPage.ctrlPageActions"></button-bar>',
            controller: CtrlPage,
            controllerAs: 'ctrlPage',
            bindToController: true
        }
    }

    angular.module('app')
        .directive('page', pageDirective);
} 


module app.page.directives {

    class CtrlBtnBar {
        private actions: string[];
    }

    function buttonBar() {
        return {
            restrict: 'E',
            replace: true,
            template: '<div class="buttonBar"><btn action="CtrlBtnBar.actions[0]"></btn><btn action="CtrlBtnBar.actions[1]"></btn></div>'
            controller: CtrlBtnBar,
            controllerAs: 'CtrlBtnBar',
            bindToController: {
                actions: '='
            }
        }
    }

    angular.module('app')
        .directive('buttonBar', buttonBar);
}

module app.page.directives {
    class CtrlBtn {
        private action: string;
        handleClick(){
            if (action === 'goNext'){
                CtrlPage.goNext(); /// Here is where I need help
            }
        }
    }

    function btnDirective(){
        return {
            restrict: 'E',
            replace: true,
            template: '<input type="button" value="someCaption" ng-click="CtrlBtn.handleClick()"/>',
            controller: CtrlBtn,
            controllerAs: 'ctrlBtn',
            bindToController: {
                action: '@'
            }
        }
    }

    angular.module('app')
        .directíve('btn', btnDirective);
}

If you run the code in http://www.typescriptlang.org/Playground you will see that typescript understandably objects to CtrlPage reference from within btnDirective controller CtrlBtn, because within this context CtrlPage does not exist. Must we use angular $scope to access the "goNext" method, given that the btnDirective is dumb and is not aware of its parents controllers and only receives inputs from its attributes? Taking radim's tip into consideration I guess the answer is yes.

Kieran Ryan
  • 593
  • 2
  • 8
  • 18

1 Answers1

2

Typescript with AngularJS (ver 1) does NOT bring any change to angular's architecture/design. So scopes are scopes, and they will be inherited as they did (via .$new())

Also, any Typescript class inheritance has no impact on $scope inheritance. And that won't change even with Angular 2. If some component (a bit like controller class in Typescript today) will be using code from its parent (derive from it) - in runtime it will has no effect on its context.

So, use the angular as you did, just profit from strongly typed language support.

Check these Q & A with working examples with directives:

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • It looks like the question addresses the usage of lexical 'this' in controller classes. And this behaviour isn't related to TS directly, again. – Estus Flask Dec 05 '15 at 19:32