angular-light icon indicating copy to clipboard operation
angular-light copied to clipboard

Native classes controllers not working

Open rumkin opened this issue 8 years ago • 6 comments

There is an issue with native class controllers in Chrome. Controller like this:

alight.ctrl.test = class {
    constructor() {;
        this.value = 1;
    }
};

and html like this:

<div al-ctrl="test"></div>

could not be initialised due to new error:

Error in controller: test Class constructor  cannot be invoked without 'new' Object {name: "test", env: Object, scope: d, element: div} TypeError: Class constructor  cannot be invoked without 'new'

rumkin avatar Feb 24 '17 13:02 rumkin

Wow... I didn't expect to see some bad limitations in native classes:

  1. impossible to call constructor (not class) without new, so impossible to use old way to create controller
  2. impossible use "this" in constructor before super, so Scope functions ($watch, $scan) will not work in constructor, (because they should be prepared for this)

so, probably proper way to inherit it from some class Controller

class Main extends alight.Controller {
  constructor(option) {
    super(option);
    this.name = 'Hello!';
  }
};

Also I want to try some trick with temporary "this" for scope functions, maybe it will works...

lega911 avatar Mar 04 '17 09:03 lega911

I think it would be proper way to instantiate controllers with new always.

rumkin avatar Mar 06 '17 10:03 rumkin

Yes, but in this case, it's impossible to pass scope as first arguments into constructor, like it works now - broken compatibility. or "this" will not have system functions like "$watch/scan"

lega911 avatar Mar 06 '17 12:03 lega911

In this case the better way is to use alight.Controller. As I see Scope interface is changed in v0.14 and it is not backward compatible.

rumkin avatar Mar 06 '17 12:03 rumkin

I think that controller could looks like that:

class Controller {
    constructor(scope, el, expr, env) {
        this.$scope = scope;
        this.$el = el;
        this.$env = env;
        this.$expr = expr;
        
        this.$init();
        
        scope.$watch('$destroy', this.$destroy.bind(this));
    }
    
    $init() {
        
    }
    
    $destroy() {
        
    }
}

rumkin avatar Mar 09 '17 12:03 rumkin

And I think that scope should not be mixed in controller. I'd prefer to assign controller to $this scope's property.

rumkin avatar Mar 13 '17 19:03 rumkin