javascriptcoffeescripttwitter-flight

CoffeeScript classes in twitter Flight


I woud like to define flightjs components with CoffeeScript classes instead of functions but it seems to not be possible because flight ignores objects' prototypes. I can't write:

define ['flight/component'], (defineComponent) ->
     class MyDropdown
          constructor: () ->
               @defaultAttrs #attrs
               @after 'initialize', () ->
                  #doSmth

          func1: (evt, data) ->
          func2: (evt, data) ->

     return defineComponent MyDropdown

Instead of

define ['flight/component'], (defineComponent) ->

    return DefineComponent () ->

        this.func1 = (evt, data) ->
        this.func2 = (evt, data) ->

        this.defaultAttrs #attrs
        this.after 'initialize', () ->
            #doSmth

Because first sample of code binds func1 and func2 to MyDropdown prototype

MyDropdown.ptototype.func1

So only workaround I found out is to create 'proxy' class to bind prototypes methods in constructor when it's already flight component:

define [], () ->
    class FlightComponent
        constructor: (childClass) ->
            # constructor is ommited because I don't want to override component's constructor
            @[name] = func if name isnt 'constructor' for name, func of childClass.prototype

    return FlightComponent


define ['flight/component', 'js/FlightComponent'], (defineComponent, FlightComponent) ->
     class MyDropdown extends FlightComponent
          constructor: () ->
               super MyDropdown
               @defaultAttrs #attrs
               @after 'initialize', () ->
                  #doSmth

          func1: (evt, data) ->
          func2: (evt, data) ->

    return defineComponent MyDropdown

I think it's awkward that I have to call parent constructor with class as parameter to make it works with flight API. I coud get over parent class and just write code inside at the begining of the constructor but I find inheritance more flexible (fe. if I'll add DataComponent and Component classes in future).

So I'm wondering is there any better way to use full futures of CoffeeScript with Twitter Flight?

It seems to be counterintuitive that flight does not allow to bind methods to object prototype... Or do I miss something?

Edit

Best solution I found out for now:

define ['flight/component', 'js/mixin1', 'js/mixin2'], (defineComponent, withA, withB) ->

     class MyDropdown extends defineComponent withA, withB

          constructor: ->
               # yay, got access to mixins, component and MyDropdown's prototype methods

Solution

  • Best solution I found is to simply extend component with mixins.

    js/withAB

    define ['flight/component', 'js/mixins/mix1', 'js/mixins/mix2'], (defineComponent, withA, withB) ->
    
        defineComponent withA, withB
    

    js/myComponent

    define['js/withAb'] (componentWithAB) ->
    
        myComponent extends componentWithAB
    
            constructor: ->
                @defaultAttrs
                    name: 'selector'
    
                @after 'initialize', ->
                    @on 'smth', 'event', @method1
    
            method1:->
               # code
    

    In code

    require 'js/myComponent', (myComponent) ->
         myComponent.attachTo 'selector'
    

    This way myComponent is class that extends flight's api component and has both mixinx methods. Another component may easily extend this class, override some methods and define it's own constructor.

    Defining component as class instead of function helps keeping components distinct from mixins. Also code structure is better in class because all logic that happens after object initialization (not component initialization!) is placed in constructor while all functions are binded to prototype.

    In my real life app instead of bootstrap file js/withAB I've written function that takes mixins (or nothing) as arguments and returns component instance with them mixed in.