{"componentChunkName":"component---src-templates-blog-post-js","path":"/mvc-is-dead-even-for-angularjs/","result":{"data":{"site":{"siteMetadata":{"title":"Fabrizio Fortunato","author":"Fabrizio Fortunato","siteUrl":"https://izifortune.com"}},"markdownRemark":{"id":"3c09471f-6dee-5e8a-9dd7-4526bba2372b","excerpt":"MVC is dead, MVC will remain dead. It served us well over those years but it’s time to explore and use better alternatives for state management in AngularJS…","html":"<p>MVC is dead, MVC will remain dead. It served us well over those years but it’s time to explore and use better alternatives for state management in AngularJS.</p>\n<h2>Intro</h2>\n<p>This article is a follow up of the talk that i give for <a href=\"https://twitter.com/AngularJSDublin\">AngularJSDublin</a>. I have to thank all the guys attending the meetup for the awesome feedback that i received.</p>\n<p>Let’s start by analyzing very high level the evolution of the FE architecture patterns.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 590px;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/dist/static/5b72da2ad1d5fad29fe40b72e55aee1e/23d69/redux_timeline.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 45.27027027027027%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAAAsSAAALEgHS3X78AAACI0lEQVQoz2NgMOtmDJ96Ujli6imr0CknJRgggNGjbjV32MTDhk4VizlA/J9AXFG7mDNx4iHD6vwJbGfERBinsU5kTG04wR476ZR+cvsJ7u8MyQwM7OmrV3JkrFnOm712OVvG2uXsyYtXMhj4rmTQsFvJbuC2gkHTYQW7lsPKJXrGK3fpGazYbmK+Yru+4cqNBlYra91Wryzx2r+y2m/vijLP3StKvfasBBkozZ21VpEvZ50me+Y6aaCBsgyGvjIMmvayHIYe2gyajjJAA2WW6hnLAg2U3mZqqbndwEgeaKA00EAZoIEyVf57tYGGyQANlWGAAY2a7ewMaEDSPoQLXWyfuxcnulhzzGGEuv///zMw+M9jZWAthRgYMo/RMjKbkYHDiBHI4wzLLmEQMfdlXK6pC+IztDAwcKyRlmO+0jOXoclzBeP0iguM+gwzOWM11zN0pR4Dq2GInXOCbdKeW0og9slr98GC/kC8dPVaVZjF39dvBNPP9+5VuWBtx4zswt3L7qmiOHnrpWc1l179/n/41msnmNiCrQezJ2w59X/R7pPBMLHPp88Gvl2z7v/9XbuzYWK3zr0Nfnn3z//bF95mwg1cfvJh8srTjx4duPHKGCa24ui10KX7zjxasmG7A9zAC5ccHq1b//jJgYOhMLG7l945PLzx4dHdy++CEWGIBJ69fs/IABX7//8ymO5fvZnh//t3KOpPAen//3+j6AXJAQBDqN8HKmXXFAAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"FE Architecture\"\n        title=\"FE Architecture\"\n        src=\"/dist/static/5b72da2ad1d5fad29fe40b72e55aee1e/102e5/redux_timeline.png\"\n        srcset=\"/dist/static/5b72da2ad1d5fad29fe40b72e55aee1e/83276/redux_timeline.png 148w,\n/dist/static/5b72da2ad1d5fad29fe40b72e55aee1e/ba02f/redux_timeline.png 295w,\n/dist/static/5b72da2ad1d5fad29fe40b72e55aee1e/102e5/redux_timeline.png 590w,\n/dist/static/5b72da2ad1d5fad29fe40b72e55aee1e/23d69/redux_timeline.png 710w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>Before 2010 we can say that Jquery was the absolute king on the FE. Who doesn’t remember those days i can tell you it was mainly spaghetti code</p>\n<p>In 2010 frameworks like Backbone started to introduce MVC in their core, what they called MV* most of the time.</p>\n<p>Backbone and other frameworks a like took this pattern from the BE, and it was great thanks to the big separations of concerns that MVC brought to the FE.</p>\n<p>In 2012 AngularJS v1 was released, 4 years ago really that long. Also AngularJS followed the MV* approach introducing something even more powerful on top of it.</p>\n<h2>2 way binding</h2>\n<blockquote>\n<p>Any data-related changes affecting the model are immediately propagated to the matching view(s), and that any changes made in the view(s) (say, by the user) are immediately reflected in the underlying model. When app data changes, so does the UI, and conversely —Stackoverflow</p>\n</blockquote>\n<p>Now all our views will update when the model change and vice versa. That was the real superpower of angular.</p>\n<p>If we take 2 way binding and apply it over AngularJS components, if we update a property on the child it will be updated also on the parent and same thing apply for parent child.</p>\n<p>This is a common use of two way binding for components communication.</p>\n<div class=\"gatsby-highlight\" data-language=\"language-javascript\"><pre class=\"language-language-javascript\"><code class=\"language-language-javascript\">.component(&#39;parent&#39;, {\n  controller() {\n  }\n})\n\n.component(&#39;child&#39;, {\n  bindins: {\n   twoWay: &#39;=&#39;\n  },\n  controller() {\n  }\n});</code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"language-html\"><pre class=\"language-language-html\"><code class=\"language-language-html\">&lt;!-- Parent --&gt;\n&lt;child\n  two-way=&quot;$ctrl.twoWay&quot;&gt;\n&lt;/child&gt;\n\n&lt;!-- Child --&gt;\n&lt;input ng-model=&quot;$ctrl.twoWay&quot; type=&quot;text&quot;&gt;</code></pre></div>\n<p>I like to compare for this 2 way binding to alcohol:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 480px;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/dist/static/7c71264019ccc24d14e9488171f1159c/c9161/homer.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 75%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsSAAALEgHS3X78AAADFElEQVQozx3QWXPbVACG4RPJrjdJdmzHi2wlVrRbu7Uc60hHi/c1pCTlgm5QmKEwtJThgv58XO6+m2e+mRd4il2E0RKGKny6wZ8G6V/D/J9x9nmAPw+TP3j7UdewL6gp2y1uakmrktCllCKTBrFo10Co+0UA13E24cQm0xyMxa6IY99LFou76N0b3FhdA1QBSf0KN4iMIhKqFDcu/oKrFxx8wyjzprKjjByxp7CU0K2co+qr7ejdnjIZENTJhCIzmsyZUsF8GwlFLC8Ymf4yjPIgyqF7WMcJNFNoYGhvY+XT+82r41bletKAVjpVlSnpFAgokNBERhOrbg2s4Xw1j1MfYt9aJjNp1J7Jgj4ZFCj68+PXv397fnviEs/IQi12ZWjwM4m1hsyBY85CBxQhWvz/nAbOAtmuKj6Gu71sY/fBQf/mxU8/n7qpJc1VOTalxJYWc+uE3KJZWnYqIAjxKpwvoySD7hJ76l0PamYk3LvaQXa/aM7vxwQ9+tlBmR2nwd6AyNGOkZ1TV8vrKnD8GHthBlEa2Os8zCIHhQbyBdd7MN03pv/Rs3FsSdgxsaHh6TR2lFPsZNTVqvsCuOk+Xz1H+CFwHQydFQ5jS4Aa78iSzouWMgsUHmpcYt2vk2CfRadleozdnCIwWwN2en5ce087pEpObtLRVIF9oHYqEUvMesR8RBa3wOw3vB7hClMc7BdwvgmtlAbFsA8UP4vU5grLmunh2PQ1A7JlrdeYjysztoa4anFHOizjDcvIiQ8o2njCDzstH5bybhMovda0WQ4nHaiK+oBP1IHBMla/Yo8Yl6WdIe2PG0a/qd60Nr799aX6ehv9uOZ/xeOzPwR8nXwKWuFty2p3izpYaQ2XrewEcieRAVvmGXLar5iDpj641uhSeFPdmNyHfefLw+T1dgy06+ppXNZYdnqpatZNkRbbtZwvHbSy3H4xrgOOIiYh0gzZqAOBvDJ0fx97HxLpqHdBzDLP4vh5rqVHDv3SnsWM2C5F9zXE1ietKlcHd70md/5+gpB5O5EnxjoNXwYLZH2n6Pl/YDacc8ON91gAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Homer\"\n        title=\"Homer\"\n        src=\"/dist/static/7c71264019ccc24d14e9488171f1159c/c9161/homer.png\"\n        srcset=\"/dist/static/7c71264019ccc24d14e9488171f1159c/83276/homer.png 148w,\n/dist/static/7c71264019ccc24d14e9488171f1159c/ba02f/homer.png 295w,\n/dist/static/7c71264019ccc24d14e9488171f1159c/c9161/homer.png 480w\"\n        sizes=\"(max-width: 480px) 100vw, 480px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<blockquote>\n<p>It’s the solution and cause to all the AngularJS problems.</p>\n</blockquote>\n<p>Try to imagine when your application start to grow and you have multiple children connected to the same parent and all of them are changing your <code class=\"language-text\">twoWay</code> model.</p>\n<p>What it looks time to me is:</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 590px;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/dist/static/f65dd5ab00ffb81adf720875f08a0a1e/23d69/solitare_filter.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 56.08108108108109%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsSAAALEgHS3X78AAACJElEQVQozxWQW0/bQBSEdxPEAxIiqCAFUvHWUKAkXJoSICiBBHLz2muvvfeLvbah/f9/oIk0T0czmu8MAPsQ9GBj0GjcNuAVhL8g7DVADxw9H6E4oIK6XAdRgKKFMBwnyBgqRLois92LXQAPIBzA5p9mc9hsPmy187gDHkB3+YMLJgyrqry/vM505Ky6XlwZR8Nshdni96wPYAs2HhtgCMAzACMAXgAcQzAG9/je5kYZLkvWQ5efpaMimsu3opJEogG+CdB0GwZPoDM7vUX97rp7hS6GaHgZXEYszFjiNLeVWtOPwqp1Mtea1H+NUSTCi+l0U9UCZ8uOt+yzMGWuK6e9M191WX0VGSe5YXXlis3VcSGp0lSalKaI0XA5n4DmtybiM6+pssTklKu08Kqsna+t9dppZg0rv/Ly09lC5KUUOmFZhO1H7/UctE+OaRYIgbkk2jJfqDjDRrO8NLYylZFVZcfTcVFuvk+X63dfS8ni2L73pxfge+fEGSIVoRSnWeS92ixcOOnybf+/yknNV+EC4ZXUGZMbOsZT5DkKgjdw1jnxjkoRW8eSFG/ndaLwxltZe1eXTlDCFB1NRi+TkTTMeqlZ5FOUhXPQOW0zgXPHuEg2JsGJKYxx0gomFc+tEizDJFzj9d3g/vxn93U2IWih04CEiy02YzGhOE5CKlmaJqqwxgin5NPLKIlQJugao2TDGqP+3U3rsLW3t3d4eNBuH/8HrTS5qeAq7n0AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Solitarie\"\n        title=\"Solitarie\"\n        src=\"/dist/static/f65dd5ab00ffb81adf720875f08a0a1e/102e5/solitare_filter.png\"\n        srcset=\"/dist/static/f65dd5ab00ffb81adf720875f08a0a1e/83276/solitare_filter.png 148w,\n/dist/static/f65dd5ab00ffb81adf720875f08a0a1e/ba02f/solitare_filter.png 295w,\n/dist/static/f65dd5ab00ffb81adf720875f08a0a1e/102e5/solitare_filter.png 590w,\n/dist/static/f65dd5ab00ffb81adf720875f08a0a1e/23d69/solitare_filter.png 710w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>There are some alternative ways and they mainly comes from the React world. In 2015 Redux was released and it is probably the most famous implementation of Flux. What actually Redux and Flux bring to the table?</p>\n<h2>One way dataflow</h2>\n<blockquote>\n<p>The model is the single source of truth. Changes in the UI trigger actions/messages that signal the intent to change the model.</p>\n</blockquote>\n<p>One way dataflow is a deterministic approach while two-way binding can cause side effects and that’s what we are trying to avoid.</p>\n<p>To apply one way dataflow i recommend use a fantastic manual by Todd Motto: <a href=\"https://toddmotto.com/stateful-stateless-components\">stateful-stateless-components</a>.</p>\n<p>If we want to convert the previous example using one way dataflow:</p>\n<div class=\"gatsby-highlight\" data-language=\"language-javascript\"><pre class=\"language-language-javascript\"><code class=\"language-language-javascript\">.component(&#39;parent&#39;, {\n  controller() {\n    this.onTwoWayChange({value}) =&gt; {\n      this.twoWay = value;\n    };\n  }\n})\n\n.component(&#39;child&#39;, {\n  bindins: {\n   twoWay: &#39;&lt;&#39;,\n   onChange: &#39;&amp;&#39;\n  },\n  controller() {\n    this.modelChange = (value) =&gt; {\n      this.onChange({\n        $event: { value }\n      });\n    };\n  }\n});</code></pre></div>\n<div class=\"gatsby-highlight\" data-language=\"language-html\"><pre class=\"language-language-html\"><code class=\"language-language-html\">&lt;!-- Parent --&gt;\n&lt;child\n  two-way=&quot;$ctrl.twoWay&quot;\n  on-change=&quot;$ctrl.onTwoWayChange($event)&gt;\n&lt;/child&gt;\n\n&lt;!-- Child --&gt;\n&lt;input\n  ng-model=&quot;$ctrl.model&quot;\n  ng-change=&quot;$ctrl.modelChange($ctrl.model)\n  type=&quot;text&quot;&gt;</code></pre></div>\n<p>What we are gaining here is: consistency with angular 2 components communication and predictable changes of our model and we also finally decoupled the child components from the parent.</p>\n<p>Those components are also called stateful and stateless components:</p>\n<ul>\n<li>\n<p><em>Stateful component</em></p>\n<p>Stores information about the app, has the ability to change it and also will render child components.</p>\n</li>\n<li><em>Stateless component</em></li>\n</ul>\n<p> It render it’s inputs and send an output</p>\n<h2>Kill MVC</h2>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 590px;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/dist/static/8ca7183915482ca20242513c97f0a42e/23d69/kill_mvc.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 52.02702702702703%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsSAAALEgHS3X78AAACEElEQVQoz02Ri0/aUBTGL7JZWqD33lIeM3FO5gabbkwJZAlTlMQxGG4O2EQBlYcFC6XyKo8KFJgT/avXikuWnNzknnvu+X7nO2ByBecxFtVAoxorbpuzAHQO6d8SUpP/CtC0bupzzm4mvLrEpmLUfQeBx+c6HPK4X2DGdculh0o/1Q04LanU4H//YSf/qhRdd9rh8TfjnYTAo2wNDS9xL8cMBfYE6YtrxL1smbXgrA3/tLSCaZ3uleyD+qbMb4U2bccxo6Y8URurwDUNbNJgKmH6AICEi4zsmaM7xmTElP1uvq7Amwbdvngm8y9vOh/868zRV+McWxtMVVZU8SqbdJJfANh7bUB40e0k37nIXb+xW6JvmlDiHNLFi2nbF9uxnhw8YI+qWBHwuIYnIhrybNROROmFTJR2OQ1+D+V7Twa8lHBG30mQS9n4zOq47RPP1qppqLbTlDVg7cTtU8YHdEcbBiEHA1uG0EcyEqQCXkMiTN02YTm53CutKI2NTtndzKFpA86x0aiqXpjzEP0GgKs4nY2bAABLNr2D1Tus+vA2IXG4lbNMxeetnCOfWCmnaNVIoIhIqaI+x8gl6+4y8VYH5CIu/DR73Iv7AZWcCPqJz58o8Vybq1ewdznm1z57+sM8m69KW2YNN7OMa0HnRU+kPB4JcMA/GClqS6qk8XUFTQRGLlqHFRQP4uyhWTXsL4R7o8hx67VPAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Uma Thurman\"\n        title=\"Uma Thurman\"\n        src=\"/dist/static/8ca7183915482ca20242513c97f0a42e/102e5/kill_mvc.png\"\n        srcset=\"/dist/static/8ca7183915482ca20242513c97f0a42e/83276/kill_mvc.png 148w,\n/dist/static/8ca7183915482ca20242513c97f0a42e/ba02f/kill_mvc.png 295w,\n/dist/static/8ca7183915482ca20242513c97f0a42e/102e5/kill_mvc.png 590w,\n/dist/static/8ca7183915482ca20242513c97f0a42e/23d69/kill_mvc.png 710w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>Now that we have introduced one way dataflow applied to components we can also <em>kill</em> MVC directly. The problem is not really about MVC, rather that FE apps have become more and more complex over the years and MVC has always coupled our controllers directly to our views with the consequences that our code cannot respond to rapid changes as it’s usually the case.</p>\n<h2>Redux</h2>\n<blockquote>\n<p>Redux is a predictable state container, the purpose of Redux is to make state mutations predictable.</p>\n</blockquote>\n<p>The three principles of Redux are:</p>\n<ul>\n<li>\n<p>Single source of truth</p>\n<p>The state of your app is stored inside a single store</p>\n</li>\n<li>\n<p>State is read only</p>\n<p>The only way to change the state is to emit an action which is an object describing what happen.</p>\n</li>\n<li>\n<p>Changes are made with pure functions</p>\n<p>To specify how the state is transformed by actions you write pure reducers.</p>\n</li>\n</ul>\n<p>A <em>reducer</em> is a pure function that take the previous state and an action and return the next state.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto;  max-width: 590px;\"\n    >\n      <a\n    class=\"gatsby-resp-image-link\"\n    href=\"/dist/static/8308610a7be96329f07330a8d638006d/23d69/redux_flow.png\"\n    style=\"display: block\"\n    target=\"_blank\"\n    rel=\"noopener\"\n  >\n    <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 41.21621621621622%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsSAAALEgHS3X78AAABtklEQVQoz2NgQAK7Qm3A9LpASwZJESFGEFtIVChQQEjgrKCwYDyILyMsyJhmpgFXvyPEhgEDCItJMPALizLqqagyHApHKLBiYGCRVpF5rG6p+V9WQ+6zKAODIEzucIQdAwMvLwPQMkZBEYgwkA0iRBjhJoiqgtm1Njosx6Ps+UFsfmHBKUDX/RcQEVz6f2M5y7N0d94oPWVmkJy2oQpcL9AnjMiOBCmQgHjXmvd/Vyynhawk0EA2iKF8fDpQdbyKosJC/2vDuNYGWnKBBJgYGMWh+hmExIQZGSQU1FjFZZXXi8ko/ZCSVcwGSbDx8MpKiAiclxETeCUowOcMEtORErUFGvZSRVz4gomchDJITEpBMlVUSuy7mIzYJmDQcICt5BcQVJPXNvuvYe39X1JB/TQ4LPgEotTkRP4bq4n/5+flmwMSs1GUmuioIvPfQ03uv4OydDpIDBiux9TMNP7L6yj+B7pOF+5fXl7eDh4e7qtAwz1AfHVZIX5+fr6VQPGj0mICmmBL+PnUuHl5D3Pz8K4GygpB9bny8PBcAdLdDLgABzsTI7oYJy8PE7oYKysHhjphcREGAD3bTStWRDihAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Redux diagram\"\n        title=\"Redux diagram\"\n        src=\"/dist/static/8308610a7be96329f07330a8d638006d/102e5/redux_flow.png\"\n        srcset=\"/dist/static/8308610a7be96329f07330a8d638006d/83276/redux_flow.png 148w,\n/dist/static/8308610a7be96329f07330a8d638006d/ba02f/redux_flow.png 295w,\n/dist/static/8308610a7be96329f07330a8d638006d/102e5/redux_flow.png 590w,\n/dist/static/8308610a7be96329f07330a8d638006d/23d69/redux_flow.png 710w\"\n        sizes=\"(max-width: 590px) 100vw, 590px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n  </a>\n    </span></p>\n<p>If you want to learn more about Redux i strongly recommend to read the online documentation that you can find at <a href=\"http://redux.js.org/\">http://redux.js.org/</a> </p>\n<h2>ng-redux</h2>\n<p>On angular 1 applications you can use <a href=\"https://github.com/angular-redux/ng-redux\">ng-redux</a> a relative small library that will connect the store to the angularjs world.</p>\n<p>Here’s is an example on how to connect to create a store:</p>\n<div class=\"gatsby-highlight\" data-language=\"language-javascript\"><pre class=\"language-language-javascript\"><code class=\"language-language-javascript\">.config(function($ngReduxProvider) {\n  $ngReduxProvider.createStoreWith(reducers, middlewares, enhancer, {});\n})</code></pre></div>\n<p><code class=\"language-text\">createStoreWith</code> take as first argument a single reducer composed of all other reducers. To check the additional arguments you can have a look at the documentation here\n<a href=\"https://github.com/angular-redux/ng-redux\">https://github.com/angular-redux/ng-redux</a>.</p>\n<p>Let’s take a look on how to connect a component to the store</p>\n<div class=\"gatsby-highlight\" data-language=\"language-javascript\"><pre class=\"language-language-javascript\"><code class=\"language-language-javascript\">export const ReduxComponent = {\n  template,\n  controller($ngRedux, ReduxActions) {\n    &#39;ngInject&#39;;\n\n    const mapStateToThis = (state) =&gt; {\n      return {\n        slice: state.slice\n      };\n    };\n\n    this.unsubscribe = $ngRedux.connect(\n      mapStateToThis,\n      ReduxActions)((state) =&gt; {\n        Object.assign(this, state);\n      });\n  }\n};</code></pre></div>\n<p>When the component initialize we connect to the store using <code class=\"language-text\">$ngRedux.connect</code> where we pass a function to slice the state and the actions that we want to connect and will return a function with the state sliced. </p>\n<p>The actions will be available directly to the controller of the connected component so you can just call the actions\nto trigger them.</p>\n<p>Remember always to unsubscribe from further store updates using the function returned from the connect, just adding on the  eg:</p>\n<div class=\"gatsby-highlight\" data-language=\"language-javascript\"><pre class=\"language-language-javascript\"><code class=\"language-language-javascript\">controller($ngRedux, ReduxActions) {\n  ...\n  this.$onDestroy = () =&gt; {\n    this.unsubscribe(); \n  };\n}</code></pre></div>\n<h3>Async reducers</h3>\n<p>All <em>ng-redux</em> documentation covers only the case of reducers defined at the start of our application. For simple application this is enough to cover your needs but on large applications where you are probably using <a href=\"https://oclazyload.readme.io/\">ocLazyLoad</a> there will be scenarios where you don’t want to load reducers upfront, but instead leveraging lazy loading of modules, the module itself should add a reducer dinamically to the store.</p>\n<p>For dinamically load reducers just using redux you can follow this stackoverflow (<a href=\"http://stackoverflow.com/questions/32968016/how-to-dynamically-load-reducers-for-code-splitting-in-a-redux-application\">http://stackoverflow.com/questions/32968016/how-to-dynamically-load-reducers-for-code-splitting-in-a-redux-application</a>).</p>\n<p>Now in AngularJs we have another layer on top of Redux that initialise the store for us.\nA solution which i need to thank Krisztián Huterják for it a coworker of mine is the following: </p>\n<div class=\"gatsby-highlight\" data-language=\"language-javascript\"><pre class=\"language-language-javascript\"><code class=\"language-language-javascript\">.config(function($ngReduxProvider) {\n  &#39;ngInject&#39;;\n  $ngReduxProvider.createStoreWith(state =&gt; state, middlewares, enhancer, {});\n})</code></pre></div>\n<p>We initialize the store with the reducers that we have available at that time, in this case its just the identity function. This code should be included into your main module that is always loaded.</p>\n<p>Then we decorate <code class=\"language-text\">$ngRedux</code> adding the ability to addReducers on the fly.</p>\n<div class=\"gatsby-highlight\" data-language=\"language-javascript\"><pre class=\"language-language-javascript\"><code class=\"language-language-javascript\">.config(($provide) =&gt; {\n  $provide.decorator(&#39;$ngRedux&#39;, ($delegate) =&gt; {\n    const reducers = {};\n\n    const rootReducer = (state, action) =&gt; {\n      const keys = Object.keys(reducers);\n      if (keys.length === 0) {\n        return Object.assign({}, state);\n      }\n      const nextState = Object.assign({}, state);\n\n      keys.forEach(key =&gt; {\n        nextState[key] = reducers[key](state[key], action);\n      });\n      return nextState;\n    };\n\n    $delegate.addReducers = (reducersObject) =&gt; {\n      Object.assign(reducers, reducersObject);\n    };\n\n    $delegate.replaceReducer(rootReducer);\n\n    return $delegate;\n  });\n})</code></pre></div>\n<p>And when we need to add a new reducer we then simply call <code class=\"language-text\">addReducers</code>.</p>\n<div class=\"gatsby-highlight\" data-language=\"language-javascript\"><pre class=\"language-language-javascript\"><code class=\"language-language-javascript\">.run(function($ngRedux) {\n  $ngRedux.addReducers(asyncReducer);\n})</code></pre></div>\n<h2>Conclusion</h2>\n<blockquote>\n<p><em>MVC</em> is dead, <em>MVC</em> remains dead, and we have killed him. How shall we <em>model</em> our apps, the murderers of all murderers!</p>\n<p>What was the holiest and mightiest of all that the <em>frameworks</em> had, yet owned has bled to death under our <em>typing</em>.</p>\n<p>Who will wipe this <em>pattern</em> off to use?</p>\n<p>What <em>approach</em> is there for us to <em>use</em> ourselves?</p>\n<p>What <em>flow</em> of atonement, what sacred <em>pattern</em> shall we to invent?</p>\n<p>Is not the greatness of the deed too great for us?</p>\n<p>Must we ourselves embrace the <em>flow</em> simply to appear worthy of it?</p>\n</blockquote>\n<p>This is a paraphrase of <em>God is dead</em> from Thus spoke Zarathustra, instead of embracing nihilism you can embrace Redux.</p>\n<p>Thank you.</p>\n<h2>Links</h2>\n<ul>\n<li><a href=\"https://toddmotto.com/stateful-stateless-components\">Stateful and stateless components, the missing manual - Todd Motto</a></li>\n<li><a href=\"https://medium.freecodecamp.com/is-mvc-dead-for-the-frontend-35b4d1fe39ec#.r5wojdan8\">Is Model-View-Controller dead on the front end? - Alex Moldovan</a></li>\n</ul>","frontmatter":{"title":"MVC is dead - even for AngularJS","date":"December 30, 2016","description":null,"socialImage":{"childImageSharp":{"fixed":{"src":"/dist/static/949891855b8d43e91ca4062f27375692/bdf9d/gravestone.png"}}},"image":{"childImageSharp":{"fluid":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsSAAALEgHS3X78AAADJElEQVQozw2RWXOiaABF+Q893V2TThtbIjt8iLIpCAIqiwYQxQWFoIlxS6aTVCZrV8/D1Pzuseo83JdTdW9dSFQpw5UsR3IDpe0JyfXUHrR1lxmluhs2L6YXg8XUDRWz16B5jObREn52dl788uenz18/QU5E+gmIl8JsI2d39avH1vbVTXeuNzRbjtawtGbXdKfq/E7PH4x4IweZ4MQVtY0xLAyFc2a6Fo7a6rG5feusn2ypyaMkDaNkGSNhlIARvAgjZRK9mDXyJ318yw83lSAHRvQDGl1W0p10/dDcvRgPv+37D4eTWIxiAMcxHEezLAkAQhDfi3BvLl1/WMlPdXwQ/SWwJmUoWXHZXlzd16+e5PVbY/NbaVhVgmJolqlUOYYFNAA4SSI4trhX17/U/G81e1CSvRjmLDRakfNbafPs7N+97EXMXnlJr2IEIYi843SDwBfEGgAkBej4IC9eapNbNlpT/hLvpQjkXf6I97Xte3D3zyh/kVfvQsPkaIqSRE7T6i2tIQocAARboec/5eWb+Pzv+td/jw8fV8OkCnUWZ3Ze6N0U/QM8usfSd7blVQFNyVJVUWRFkXihQhIoWyOyJ3n5yi+ftd2rv33sx2kFsqYFLz8PbpDoQA4OSPwXqGtVisBZQB45FmZoHMfLJIMnd0L2VIu3VH9VtlPYnBShTnLWTYveJRyvmdmeXaw93/dNU2lbarerm6aq642WoeiGPl62p3vmuNZLESfBzGEJao2/WfMzL0eGWxDvmFZXamp12265PetI/6Jju+ZRritiq1ufbLjBivQSxJ2cG4MCJPW/qMNTa3Juz0rpTUdRGygGV6oUUyEZluQFlmaPP5ULxdNGUx6vNT9Fw4RSwxPe/gOSnBO5d2JEcDAD15usqTURFKYYBMXPKRpjWYKgUIwol8oFRasny8idlKNZ1RuQgvEVEpufdbdo9AujRLvZbJJkPIiCIAzCKDiG4SgcjKJhHPkDP4zCbJl7Y96OyhcDoBslyGoLk2yRb5aL63yRp5P5zBmpmo8afbrjc/1QDgLV6tUMFxguYziM7VZk4/sRoX76PwlF8W44zPCGAAAAAElFTkSuQmCC","aspectRatio":1.336,"src":"/dist/static/949891855b8d43e91ca4062f27375692/a5924/gravestone.png","srcSet":"/dist/static/949891855b8d43e91ca4062f27375692/17cc0/gravestone.png 167w,\n/dist/static/949891855b8d43e91ca4062f27375692/f7869/gravestone.png 333w,\n/dist/static/949891855b8d43e91ca4062f27375692/a5924/gravestone.png 666w,\n/dist/static/949891855b8d43e91ca4062f27375692/997c6/gravestone.png 999w,\n/dist/static/949891855b8d43e91ca4062f27375692/07839/gravestone.png 1024w","sizes":"(max-width: 666px) 100vw, 666px"}}}}}},"pageContext":{"slug":"/mvc-is-dead-even-for-angularjs/","previous":{"fields":{"slug":"/hello-world/"},"frontmatter":{"title":"Hello World"}},"next":{"fields":{"slug":"/demystifying-functional-programming-with-ramda/"},"frontmatter":{"title":"Demystifying functional programming with Ramda"}}}}}