-
Notifications
You must be signed in to change notification settings - Fork 3
Tutorials
For those of us new to CoffeeScript and Mithril, the challenges inherent with learning a new language, and a new framework can lead to more than a few headaches. This page is for starting out with SuperPhy and learning how to program the front-end interface. The target audience is for this is a new Coop, with experience programming, but not necessarily any experience with either Mithril or CofeeScript.
The reason we are writing a wiki article is because you are going to have a great time coding if you follow the following mindset:
I will program in the same coding style as my peers and predesessors! I will follow a Common Coding Style!
It is far easier to work with legacy code if you know what different tropes of objects do. If you work in the same style as your previous peers, you will be able to understand how they worked. I won't promise that we do things in the most efficient way possible, but we will try to at least be consistent.
You should skim or read the following links in order to get a base of knowledge to work with going forward:
- CoffeeScript Overview
- Mithril 101 - Getting Started
- Mithril 102 - How routing works
- Mithril 103 - Components
The links provided may or may not conform to the styles we are using in SuperPhy.
@
is the CoffeeScript version of JavaScript's this
keyword. We use these interchangeably, as they both mean this
when the CoffeeScript is compiled into JavaScript. Whatever feels best.
When we refer to a static
component. It is a component that doesn't have a controller to deal with interactions. All the the data displayed in the view is either passed in as arguments from a parent component, or is static data in the class. See this lesson's exercise for an example of that.
If you want to start testing things out, an empty project with the correct JSFiddle settings are linked above.
This exercise will show you how to make the simplest implementation of a Mithril view. This simply populates the document.body DOM element with a div containing a string "Hello World", when the user is at the root of the view.
m.route(document.body, "/"
"/": view: -> m('.', "Hello World!")
)
You can find a working example on here.
class Hello
class Name
constructor: (name) ->
this.name = name or "Bryce"
return
greet: () ->
return "Hello #{@name}!"
@controller: () ->
@me = new Name()
@you = new Name("Coop")
return this
@view: (ctrl) ->
m('.'
m('.', ctrl.you.greet())
m('.', ctrl.me.greet())
)
m.route(document.body, "/"
"/": Hello
)
How do I go from page to page?
Routes = {}
Routes.add = (route, class_, args) ->
args = args || {}
Routes.routes ?= {}
if route.substring(0,1) is '/'
route = route.substring(1)
Routes.routes["/#{route}"] = view: -> m.component(class_, args)
class Hello
Routes.add("/Hello", this)
class Name
constructor: (name) ->
this.name = name or "Bryce"
return
greet: () ->
return "Hello #{@name}!"
@controller: () ->
@me = new Name()
@you = new Name("Coop")
return this
@view: (ctrl) ->
m('.'
m('.', ctrl.you.greet())
m('.', ctrl.me.greet())
)
class Api
Routes.add('/', this)
@view: (ctrl, args) ->
m('.'
m('.', key) for key in Object.keys(Routes.routes).sort()
)
m.route(document.body, "/", Routes.routes)
Routes = {}
Routes.add = (route, class_, args) ->
args = args || {}
Routes.routes ?= {}
if route.substring(0,1) is '/'
route = route.substring(1)
Routes.routes["/#{route}"] = view: -> m.component(class_, args)
class SuperComponent
@view: (args) ->
args = args or {}
m('.', "This is From the SuperComponent", args)
class SubComponent extends SuperComponent
Routes.add('/', this)
@controller: () ->
@data = m.prop('')
return this
@view:(ctrl, args) ->
return super(
m('.', "This is From the SubComponent", args)
)
m.route(document.body, "/", Routes.routes)
There are two ways to bind data asynchronously into the model:
- User input
- Ajax
Both of these methods are handled by the mithril promise object: m.prop()
In the following example, we have a fake Ajax request, and a field that you can fill out. Both of these are going to be behind an object that sets and gets the data.
Routes = {}
Routes.add = (route, class_, args) ->
args = args || {}
Routes.routes ?= {}
if route.substring(0,1) is '/'
route = route.substring(1)
Routes.routes["/#{route}"] = view: -> m.component(class_, args)
fake_request = () ->
return m.prop({
headers: ['a','b','c']
rows: [
{'a':"Foo", 'b':"Bar", 'c':"Bing"}
{'a':"Alpha", 'b':"Beta", 'c':"Gamma"}
{'a':"Lorem", 'b':"Ipsum", 'c':"Dolor"}
]
})
class Promises
Routes.add('/', this)
@controller: (args) ->
@data = fake_request()
@name = m.prop("")
return this
@view: (ctrl) ->
return m('.'
m('table', {border:"1"},
m('tr', m('th', header) for header in ctrl.data().headers)
m('tr', m('td', row[header]) for header in ctrl.data().headers
) for row in ctrl.data().rows
)
m('input[type=text]'
oninput:m.withAttr('value', ctrl.name)
value:ctrl.name()
placeholder:"Name"
)
m('.', "Name = #{ctrl.name()}")
)
m.route(document.body, "/", Routes.routes)
How do I get data from a database? (model How do I change/update some data?