Tweetbox with Mithril and Redux
HTML
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/redux/3.0.4/redux.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/mithril/0.2.1/mithril.min.js"></script>
<div class="container-fluid" id="main">
<div class="row">
<div class="col-xs-12 col-md-4">
<div id="app"></div>
</div>
</div>
</div>
CSS
#main {
margin-top: 20px;
}
CoffeeScript
initialState =
text: ""
photoAdded: false
replace = (x, v) ->
Object.assign {}, x, v
vm = (state, action) ->
if state is undefined then return initialState
switch action.type
when "CHANGE_TEXT" then Object.assign {}, state, {text: action.text}
when "TOGGLE_PHOTO" then replace state, {photoAdded: !state.photoAdded}
computeProps = (state) ->
{state
,disableBtn: state.text is ""
remainingChars: 140 - state.text.length - 23*state.photoAdded
photoBtnText: if state.photoAdded then 'Photo Added' else 'Add Photo'
}
TweetBox = {}
TweetBox.controller = (props) ->
handleInput: (e) =>
props.dispatch type: "CHANGE_TEXT", text: e.target.value
togglePhoto: (e) =>
props.dispatch type: "TOGGLE_PHOTO"
TweetBox.view = (ctrl, props) ->
console.log(props)
vm = computeProps(props.getState())
m '.clearfix',
m 'h4', 'TweetBox with Mithril'
m '.well',
m 'textarea.form-control',
style:
"margin-bottom": "20px"
resize: "vertical"
oninput: ctrl.handleInput
m '.pull-right',
m 'button.btn.btn-default.btn-sm',
onclick: ctrl.togglePhoto
, vm.photoBtnText
m 'button.btn.btn-primary.btn-sm',
disabled: vm.disableBtn
, 'Tweet'
m 'span.remaining', vm.remainingChars
ReduxMithrilWrapper = (component, model) ->
store = Redux.createStore(model)
render = ->
m.render document.getElementById("app"), m(component, store)
store.subscribe(render)
render()
ReduxMithrilWrapper(TweetBox, vm)