0

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
endianness
  • 21
  • 5

2 Answers2

0

Flight takes a more aspect oriented approach to creating components. Rather than using inheritance, you inject functionality, or attributes directly into your components using mixins.

The mixin API doc page has an example of how to inject a mixin to a component.

  • Mixins are good for reused functionality. I woud like to keep components distinct from mixins. Everytime when you call defineComponent(/*mixins*/, myComponent) you create component. Usually one argument is not mixin, it's explict function for one use only that defines new component with some mixins. I woud like to replace it with coffeescript class. It's common function but with methods binded to it's prototype. These methods are ignored by utils.compose(). I find out I can extend like this: MyComponent extends defineComponent withSmth, withSmthElse This way I can document it with codo – endianness Jan 23 '14 at 22:48
0

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.

endianness
  • 21
  • 5