Joshua Muheim
Joshua Muheim

Reputation: 13195

Overwriting variables in coffee script classes and sub classes

I'm a Ruby programmer trying to create a small JavaScript library.

As I'm no big JavaScript expert I'm helping myself with CoffeeScript, fighting my way through a rather unknown territory.

The idea:

I want to create several small JavaScript widgets, all of which share some small pieces of functionality.

The shared functionality and config is in the Base class. Every widget has its own class that inherits from Base and can set its own config (and even overwrite configs of Base).

Finally, when a widget is instantiated, it can be passed an option hash, itself overwriting the default options of the widget.

It looks like this so far:

@Adg = {}

class Adg.Base
  config =
    debugMessage:   false
    hiddenCssClass: 'visually-hidden'

  # Constructor. Should not be overridden; use @init() instead.
  #
  # - Arg1: The DOM element on which the script should be applied (will be saved as @$el)
  # - Arg2: An optional hash of options which will be merged into the global default config
  constructor: (el, options = {}) ->
    @config = config

    @$el = $(el)

    for key, val of options
      @config[key] = val

    @init()

  # Dummy, must be overridden in inheriting classes.
  init: ->
    throw 'Classes extending App must implement method init()!'

class Adg.Autocomplete extends Adg.Base
  config =
    suggestionsContainer: 'fieldset'
    suggestionsContainerLabel: 'legend'
    alertsContainerId: 'alerts'

  init: ->
    # Merge config into existing one
    for key, val of config
      @config[key] = val

This works, but feels clumsy to me:

Upvotes: 0

Views: 100

Answers (1)

max pleaner
max pleaner

Reputation: 26758

I believe the following will do what you are looking for:

@Adg = {}

class Adg.Base

  @config =
    debugMessage:   false
    hiddenCssClass: 'visually-hidden'

  constructor: (el, options = {}) ->
    @config = Object.assign {}, Adg.Base.config, options
    @$el = $(el)

class Adg.Autocomplete extends Adg.Base

  @config =
    suggestionsContainer: 'fieldset'
    suggestionsContainerLabel: 'legend'
    alertsContainerId: 'alerts'

  constructor: (el, options={}) ->
    super(el, Object.assign({}, options, Adg.Autocomplete.config))

There are a couple changes I made:

  1. Using class properties rather than local variables/closure. @config on Adg.Base is read using Adg.Base.config.
  2. Using super to call the parent constructor from the child's.
  3. Using Object.assign to merge hashes.

Note that if you're using Coffeescript 2 (uninstall coffee-script and install coffeescript@next package), you can use the spread operator instead of Object.assign:

@config = {Adg.Base.config..., config...}`

Upvotes: 1

Related Questions