1<!doctype html> 2<html lang="en"> 3 4<meta charset="utf-8"> 5<title>Fluxxor - Quick-Start Guide</title> 6<meta name="viewport" content="width=device-width, initial-scale=1.0"> 7<meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> 8<meta property="og:image" content="http://fluxxor.com/fluxxor.png"> 9<meta property="og:site_name" content="Fluxxor"> 10<meta name="twitter:card" content="summary"> 11<meta name="twitter:site" content=""> 12<meta name="twitter:title" content="Fluxxor"> 13<meta name="twitter:description" content="Fluxxor is a set of tools to facilitate building JavaScript data layers using the Flux architecture."> 14<meta name="twitter:creator" content="BinaryMuse"> 15<meta name="twitter:image:src" content="http://fluxxor.com/fluxxor.png"> 16<meta name="twitter:domain" content=""> 17<meta name="twitter:app:name:iphone" content=""> 18<meta name="twitter:app:name:ipad" content=""> 19<meta name="twitter:app:name:googleplay" content=""> 20<meta name="twitter:app:url:iphone" content=""> 21<meta name="twitter:app:url:ipad" content=""> 22<meta name="twitter:app:url:googleplay" content=""> 23<meta name="twitter:app:id:iphone" content=""> 24<meta name="twitter:app:id:ipad" content=""> 25<meta name="twitter:app:id:googleplay" content=""> 26<link rel="stylesheet" href="http://yandex.st/highlightjs/8.0/styles/default.min.css">
27<script src="http://cdnjs.cloudflare.com/ajax/libs/es5-shim/3.4.0/es5-shim.min.js"></script>
vendor: 1 bytes, line 27
27
28<script src="http://yandex.st/highlightjs/8.0/highlight.min.js"></script>
vendor: 1 bytes, line 28
28
29<script>hljs.initHighlightingOnLoad();</script>
29 30<link rel="stylesheet" type="text/css" href="/style/main.css"> 31 32<a class="github-banner" href="https://github.com/BinaryMuse/fluxxor"><img style="position: fixed; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/a6677b08c955af8400f44c6298f40e7d19cc5b2d/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f677261795f3664366436642e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_gray_6d6d6d.png"></a> 33 34<div class="wrapper"> 35 <header> 36 <div class="logo-container-sidebar"> 37 <a href="/"><img src="/fluxxor.svg" alt="Fluxxor" title="Fluxxor" class="logo-svg"></a> 38 </div> 39 <div class="show-hide-nav"> 40 <a href="#" class="show-nav">Show Navigation</a> 41 <a href="#" class="hide-nav">Hide Navigation</a> 42 </div> 43 <div class="nav-list"> 44 <ul> 45 <li><a href="/">Home</a></li> 46 <li><a href="/what-is-flux.html">What is Flux?</a></li> 47 <li><a href="/guides/">Guides</a></li> 48 <ul> 49 <li><a href="/guides/installation.html">Installation</a></li> 50 <li><a href="/guides/react.html">Using with React</a></li> 51 <li><a href="/guides/quick-start.html">Quick-Start Guide</a></li> 52 <li><a href="/guides/async-data.html">Dealing with Asynchronous Data</a></li> 53 <li><a href="/guides/routing.html">Routing</a></li> 54 </ul> 55 <li><a href="/examples/">Examples</a></li> 56 <ul> 57 <li><a href="/guides/quick-start.html">Basic Todos</a></li> 58 <li><a href="/examples/carousel/">Image Carousel</a></li> 59 <li><a href="/guides/async-data.html">Asynchronous Data</a></li> 60 <li><a href="/examples/react-router.html">React Router</a></li> 61 </ul> 62 <li><a href="/documentation/">Documentation</a></li> 63 <ul> 64 <li><a href="/documentation/flux.html">Fluxxor.Flux</a></li> 65 <li><a href="/documentation/stores.html">Stores</a></li> 66 <li><a href="/documentation/actions.html">Actions</a></li> 67 <li><a href="/documentation/flux-mixin.html">Fluxxor.FluxMixin</a></li> 68 <li><a href="/documentation/store-watch-mixin.html">Fluxxor.StoreWatchMixin</a></li> 69 </ul> 70 <li><a href="/faq.html">FAQ</a></li> 71 <li><a href="/changelog.html">Changelog</a></li> 72 <li><a href="https://github.com/BinaryMuse/fluxxor">View on GitHub</a></li> 73 </ul> 74 <p> 75 <a href="https://gitter.im/BinaryMuse/fluxxor">Support and chat on Gitter</a><br> 76 <a href="https://gitter.im/BinaryMuse/fluxxor"><img src="https://badges.gitter.im/BinaryMuse/fluxxor.png"></a> 77 </p> 78 </div> 79 <div class="sidebar-info"> 80 <hr> 81 <p>Copyright © 2014 <a href="https://github.com/BinaryMuse/">Michelle Tilley</a><br> 82 Licensed under <a href="http://opensource.org/licenses/MIT">the MIT license</a></p> 83 </div> 84 </header> 85 <section> 86 <h1 id="quick-start-guide-basic-todos-example">Quick-Start Guide / Basic Todos Example</h1> 87<p>Once you have Fluxxor and React <a href="/guides/installation.html">installed</a>, it's time to build an app! Since this guide is designed to cover the basics quickly, we'll start with a <em>very</em> basic todo appânamely, this one right here:</p> 88<div id="app"></div> 89 90<h2 id="stores-and-actions">Stores and Actions</h2> 91<p>First, let's create a store to keep track of our todo items. It will respond to the following actions:</p> 92<ul> 93<li><code>"ADD_TODO"</code> - adds a new todo</li> 94<li><code>"TOGGLE_TODO"</code> - completes or uncompletes a specific todo item</li> 95<li><code>"CLEAR_TODOS"</code> - removes all complete todo items</li> 96</ul> 97<pre><code class="lang-javascript"><span class="keyword">var</span> constants = { 98 ADD_TODO: <span class="string">"ADD_TODO"</span>, 99 TOGGLE_TODO: <span class="string">"TOGGLE_TODO"</span>, 100 CLEAR_TODOS: <span class="string">"CLEAR_TODOS"</span> 101}; 102 103<span class="keyword">var</span> TodoStore = Fluxxor.createStore({ 104 initialize: <span class="function"><span class="keyword">function</span>(<span class="params"></span>
104) </span>{ 105 <span class="keyword">this</span>.todoId = <span class="number">0</span>; 106 <span class="keyword">this</span>.todos = {}; 107 108 <span class="keyword">this</span>.bindActions( 109 constants.ADD_TODO, <span class="keyword">this</span>.onAddTodo, 110 constants.TOGGLE_TODO, <span class="keyword">this</span>.onToggleTodo, 111 constants.CLEAR_TODOS, <span class="keyword">this</span>.onClearTodos 112 ); 113 }, 114 115 onAddTodo: <span class="function"><span class="keyword">function</span>(<span class="params">payload</span>) </span>{ 116 <span class="keyword">var</span> id = <span class="keyword">this</span>._nextTodoId(); 117 <span class="keyword">var</span> todo = { 118 id: id, 119 text: payload.text, 120 complete: <span class="literal">false</span> 121 }; 122 <span class="keyword">this</span>.todos[id] = todo; 123 <span class="keyword">this</span>.emit(<span class="string">"change"</span>); 124 }, 125 126 onToggleTodo: <span class="function"><span class="keyword">function</span>(<span class="params">payload</span>
126) </span>{ 127 <span class="keyword">var</span> id = payload.id; 128 <span class="keyword">this</span>.todos[id].complete = !<span class="keyword">this</span>.todos[id].complete; 129 <span class="keyword">this</span>.emit(<span class="string">"change"</span>); 130 }, 131 132 onClearTodos: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{ 133 <span class="keyword">var</span> todos = <span class="keyword">this</span>.todos; 134 135 <span class="built_in">Object</span>.keys(todos).forEach(<span class="function"><span class="keyword">function</span>(<span class="params">key</span>) </span>{ 136 <span class="keyword">if</span>(todos[key].complete) { 137 <span class="keyword">delete</span> todos[key]; 138 } 139 }); 140 141 <span class="keyword">this</span>.emit(<span class="string">"change"</span>); 142 }, 143 144 getState: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{ 145 <span class="keyword">return</span> { 146 todos: <span class="keyword">this</span>.todos 147 }; 148 }, 149 150 _nextTodoId: <span class="function"><span class="keyword">function</span>(<span class="params"></span>
150) </span>{ 151 <span class="keyword">return</span> ++<span class="keyword">this</span>.todoId; 152 } 153}); 154</code></pre> 155<p>Let's create a few semantic actions to go along with our action types.</p> 156<pre><code class="lang-javascript"><span class="keyword">var</span> actions = { 157 addTodo: <span class="function"><span class="keyword">function</span>(<span class="params">text</span>) </span>{ 158 <span class="keyword">this</span>.dispatch(constants.ADD_TODO, {text: text}); 159 }, 160 161 toggleTodo: <span class="function"><span class="keyword">function</span>(<span class="params">id</span>) </span>{ 162 <span class="keyword">this</span>.dispatch(constants.TOGGLE_TODO, {id: id}); 163 }, 164 165 clearTodos: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{ 166 <span class="keyword">this</span>.dispatch(constants.CLEAR_TODOS); 167 } 168}; 169</code></pre> 170<p>Now we can instantiate our store and build a <code>Flux</code> instance:</p> 171<pre><code class="lang-javascript"><span class="keyword">var</span> stores = { 172 TodoStore: <span class="keyword">new</span> TodoStore() 173}; 174 175<span class="keyword">var</span> flux = <span class="keyword">new</span> Fluxxor.Flux(stores, actions); 176</code></pre> 177<p>Finally, let's use the <code>"dispatch"</code> event to add some logging:</p> 178<pre><code class="lang-javascript">flux.on(<span class="string">"dispatch"</span>, <span class="function"><span class="keyword">function</span>(<span class="params">type, payload</span>
178) </span>{ 179 <span class="keyword">if</span> (<span class="built_in">console</span> && <span class="built_in">console</span>.log) { 180 <span class="built_in">console</span>.log(<span class="string">"[Dispatch]"</span>, type, payload); 181 } 182}); 183</code></pre> 184<h2 id="react-application">React Application</h2> 185<p>Let's build out our UI with React.</p> 186<p>Our top-level <code>Application</code> component will use the <a href="/documentation/flux-mixin.html">FluxMixin</a> as well as the <a href="/documentation/store-watch-mixin.html">StoreWatchMixin</a> to make our lives a bit easier. The component will iterate over the array of todos and emit a <code>TodoItem</code> component for each one.</p> 187<p>We'll also add a quick form for adding new todo items, and a button for clearing completed todos.</p> 188<pre><code class="lang-javascript">var FluxMixin = Fluxxor.FluxMixin(React), 189 StoreWatchMixin = Fluxxor.StoreWatchMixin; 190 191var Application = React.createClass({ 192 mixins: [FluxMixin, StoreWatchMixin("TodoStore")], 193 194 getInitialState: function() { 195 return { newTodoText: "" }; 196 }, 197 198 getStateFromFlux: function() { 199 var flux = this.getFlux(); 200 // Our entire state is made up of the TodoStore data. In a larger 201 // application, you will likely return data from multiple stores, e.g.: 202 // 203 // return { 204 // todoData: flux.store("TodoStore").getState(), 205 // userData: flux.store("UserStore").getData(), 206 // fooBarData: flux.store("FooBarStore").someMoreData() 207 // }; 208 return flux.store("TodoStore").getState(); 209 }, 210 211 render: function() { 212 var todos = this.state.todos; 213 return ( 214 <div> 215 <ul> 216 {Object.keys(todos).map(function(id) { 217 return <li key={id}><TodoItem todo={todos[id]} /></li>; 218 })} 219 </ul> 220 <form onSubmit={this.onSubmitForm}> 221 <input type="text" size="30" placeholder="New Todo" 222 value={this.state.newTodoText} 223 onChange={this.handleTodoTextChange} /> 224 <input type="submit" value="Add Todo" /> 225 </form> 226 <button onClick={this.clearCompletedTodos}>Clear Completed</button> 227 </div> 228 ); 229 }, 230 231 handleTodoTextChange: function(e) { 232 this.setState({newTodoText: e.target.value}); 233 }, 234 235 onSubmitForm: function(e) { 236 e.preventDefault(); 237 if (this.state.newTodoText.trim()) { 238 this.getFlux().actions.addTodo(this.state.newTodoText); 239 this.setState({newTodoText: ""}); 240 } 241 }, 242 243 clearCompletedTodos: function(e) { 244 this.getFlux().actions.clearTodos(); 245 } 246}); 247</code></pre> 248<p>The <code>TodoItem</code> component will display and style itself based on the completion of the todo, and will dispatch an action indicating its intent to toggle its completion state.</p> 249<pre><code class="lang-javascript"><span class="keyword">var</span> TodoItem = React.createClass({ 250 mixins: [FluxMixin], 251 252 propTypes: { 253 todo: React.PropTypes.object.isRequired 254 }, 255 256 render: <span class="function"><span class="keyword">function</span>(<span class="params"></span>
256) </span>{ 257 <span class="keyword">var</span> style = { 258 textDecoration: <span class="keyword">this</span>.props.todo.complete ? <span class="string">"line-through"</span> : <span class="string">""</span> 259 }; 260 261 <span class="keyword">return</span> <span class="xml"><span class="tag"><<span class="title">span</span> <span class="attribute">style</span>=<span class="value">{style}</span> <span class="attribute">onClick</span>=<span class="value">{this.onClick}</span>></span>{this.props.todo.text}<span class="tag"></<span class="title">span</span>></span>;</span> 262 }, 263 264 onClick: <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{ 265 <span class="keyword">this</span>.getFlux().actions.toggleTodo(<span class="keyword">this</span>.props.todo.id); 266 } 267}); 268</code></pre> 269<h2 id="bringing-it-together">Bringing it Together</h2> 270<p>Now that we have a <code>Flux</code> instance and all our components are defined, we can finally render our app. We'll put it inside a <code>div</code> in our HTML with an ID of "app".</p> 271<pre><code class="lang-javascript">React.render(<span class="xml"><span class="tag"><<span class="title">Application</span> <span class="attribute">flux</span>=<span class="value">{flux}</span> /></span>, document.getElementById("app"));</span> 272</code></pre> 273<p>And that's it! We've created a (super simple) Flux application with React and Fluxxor. You can find the full source code <a href="https://github.com/BinaryMuse/fluxxor/tree/master/examples/todo-basic">on GitHub</a>.</p>
274<script src="todo-bundle.js"></script>
274 275 276 <hr> 277 See a typo? Something still not clear? 278 <a href="https://github.com/BinaryMuse/fluxxor/issues/new">Report an issue on GitHub</a>. 279 </section> 280 281 <div class="footer-info"> 282 <hr> 283 <p>Copyright © 2014 <a href="https://github.com/BinaryMuse/">Michelle Tilley</a><br> 284 Licensed under <a href="http://opensource.org/licenses/MIT">the MIT license</a><br> 285 <a href="https://github.com/BinaryMuse/fluxxor">Available on GitHub</a></p> 286 </div> 287</div> 288
289<script> 290document.querySelectorAll(".show-nav")[0].addEventListener("click", function(ev) { 291 ev.preventDefault(); 292 document.querySelectorAll(".nav-list")[0].style.display = 'block'; 293 document.querySelectorAll(".show-nav")[0].style.display = 'none'; 294 document.querySelectorAll(".hide-nav")[0].style.display = 'block'; 295}); 296 297document.querySelectorAll(".hide-nav")[0].addEventListener("click", function(ev) { 298 ev.preventDefault(); 299 document.querySelectorAll(".nav-list")[0].style.display = 'none'; 300 document.querySelectorAll(".show-nav")[0].style.display = 'block'; 301 document.querySelectorAll(".hide-nav")[0].style.display = 'none'; 302}); 303</script>
303 304
305<script>
vendor: 339 bytes, lines 305-311
305 306 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 307 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 308 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 309 })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); 310 311 ga('create', '
311UA-51086297-1
vendor: 21 bytes, lines 311-312
311', 'fluxxor.com'); 312
312ga('require', 'displayfeatures'); 313 ga('require', 'linkid', 'linkid.js'); 314 ga('send', 'pageview'); 315</script>
vendor: 1 bytes, line 315
315
316<script> 317 function appendAnchorSymbol(el, id) { 318 var anchor = document.createElement("a"); 319 anchor.setAttribute("href", "#" + id); 320 anchor.setAttribute("class", "anchor-symbol"); 321 anchor.innerHTML = "¶"; 322 el.appendChild(anchor); 323 } 324 325 var hs = document.querySelectorAll("h1,h2,h3,h4,h5,h6"), 326 h, id; 327 for (var i = 0; i < hs.length; i++) { 328 h = hs[i]; 329 id = h.getAttribute("id"); 330 if (id) { 331 appendAnchorSymbol(h, id); 332 } 333 } 334</script>
334 335 336</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.