-
Notifications
You must be signed in to change notification settings - Fork 0
Adapters
Adapters are the most unique part of pipeline. They specify an interface between the state held in the stores and some external place. They can listen to some external events and fire actions, and can listen to store change events and respond accordingly.
A common example is RouteAdapter. In contrast to a view based router like the excellent react-router, we'd like to hold our canonical location state in a store rather than the URL bar. The url bar just becomes a projection of app state from a store (and is helpful on a refresh).
Blog = pipeine.createApp()
Blog.createStore('location',
pages: ['home', 'post', 'list']
API:
getPage: -> @get('page')
getId: -> @get('id')
actions:
goHome: ->
@update(page:'home', id: null)
goToList: ->
@update(page:'list', id: @action.id)
goToPost: ->
@update(page:'post', id: @action.id)
navigate: ->
if _.contains(@pages, @action.page)
@update(page: @action.page, id: @action.id)
Blog.createAdapter('route',
stores:
location: ->
page = @stores.location.getPage()
id = @stores.location.getId()
switch page
when 'home' then window.pushState({}, '/')
when 'post' then window.pushState({}, "post/#{id}/"
when 'list' then window.pushState({}, "list/#{id}/"
Examples:
A Route Adapter
projects internal state into the URL bar via the pushState API and interprets user changes to the route (back button, etc) via popState events and fires actions accordingly.
A Network Adapter
makes network requests based on the state of a store.
React views are a special case because they can be so complex, but they are really just DOM Adapters
. They project internal application state into the DOM for the user to see and interact with, and they interpret user events and fire actions accordingly.
Any source of Asynchrony should be accessed via an adapter.
App.createAdapter(name, options)
Pantry.createApp()
Pantry.createStore 'crackers',
API:
getPrice: -> @get('price')
actions:
newCrackersPrice: -> @update('price', @action.price)
Pantry.createAdapter('crackersAdapter',
syncCrackerPrice: ->
$.ajax
type: 'PUT'
url: 'api/0/crackers/price/'
data: @stores.crackers.getPrice()
success: @actions.crackers.priceSynced
error: (xhr, error) ->
@actions.crackers.priceSyncError(error)
stores:
'crackers': ->
if @stores.crackers.needsSync() then @syncCrackerPrice()