1

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

class Component {
    constructor(app, name, template, as, bindings) {
        this.bindings = bindings;
        this.config = {}
        this.config.template = template;
        this.config.controllerAs = as;

        // pre-create properties
        this.config.controller = this.controller;
        this.config['bindings'] = this.bindings;

        app.component(name, this.config);

        console.log("Inside Component ctor()");
    }

    addBindings(name, bindingType) {
        this.bindings[name] = bindingType;
    }

    controller() {
    }
}

class App extends Component {
    constructor(app) {
        var bindings = {
            name: "<"
        };

        super(app, "app", "Hello", "vm", bindings);
    }

    controller() {
        this.$onInit = () => this.Init();             // DOESN'T WORK
        /*
        var self = this;
        self.$onInit = function () { self.Init(); };  // DOESN'T WORK
        */
        /*
        this.$onInit = function () {                  // WORKS
            console.log("This works but I don't like it!");
        };
        */
    }

    Init() {
        console.log("Init");
    }

    onNameSelected(user) {
        this.selectedUser = user;
    }
}
var myApp = new App(app);
<div ng-app="testApp">
  <app></app>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>

I'm trying to "classify" angular 1.5's .component(). I can get most of it figured out but when I try to assign a class method for $onInit it doesn't work. I've tried assigning to it and using arrow notation to call back to the class method but neither work. It does work if I assign an anonymous function directly but I don't want to do that. I want those functions to point to class methods because I find it cleaner.

So ultimately I want my App classes Init() method to get called for $onInit(). Is it possible?

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
user441521
  • 6,942
  • 23
  • 88
  • 160
  • If I change everything to just 'this' and have this.$onInit = () => this.Init();, it doesn't work. Error in console is this.Init is not a function. – user441521 Oct 03 '17 at 18:26
  • 1
    Updated the answer to have the code inline – user441521 Oct 03 '17 at 19:00
  • *"Updated the answer to have the code inline"* Great stuff! (It's a *question*, not an *answer*. :-) ) – T.J. Crowder Oct 04 '17 at 07:14
  • The proximate problem is that `this` in the call to `controller` isn't your instance (add a `console.log(this.Init);` to `controller` and you'll see it's `undefined`). That's because in `Component`, `this.config.controller = this.controller;` should be `this.config.controller = () => this.controller();` or `this.config.controller = this.controller.bind(this);` (see [this question](http://stackoverflow.com/questions/20279484/)). Doing that fixes the issue with `this` being wrong in `contoller`. But if you do that, `$onInit` never gets called (!). I don't know Angular enough to know why not. – T.J. Crowder Oct 04 '17 at 07:14
  • I was able to figure out that we can do this without any sort of base class. The settings end up being static get accessors and you set the controller to the class itself and the class constructor becomes the controller function and $onInit gets called! Even easier than I thought! – user441521 Oct 09 '17 at 15:52

0 Answers0