{
    "componentChunkName": "component---src-templates-post-js",
    "path": "/blog/2013/07/22/the-basics-of-using-ui-router-with-angularjs",
    "result": {"data":{"site":{"siteMetadata":{"title":"your friend Joel's digital garden","description":"Articles and notes from a collaborator at egghead.io. Musings on software, business, and life from a skilled virtual assistant.","author":{"name":"Joel Hooks"},"keywords":["Video Blogger"]}},"mdx":{"excerpt":"URL routing is a popular approach to matching the contents of a URL to specific\nfunctionality within a web application. URL routes programatically present\nspecific content to users based on the URL that they are visiting. It is a\npopular…","fields":{"github":"https://github.com/joelhooks/joelhooks-com/tree/master/content/legacy_blog/2013-07-22-the-basics-of-using-ui-router-with-angularjs.markdown"},"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"layout\": \"post\",\n  \"title\": \"The basics of using ui-router with AngularJS\",\n  \"date\": \"2013-07-22T00:00:00.000Z\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"URL routing is a popular approach to matching the contents of a URL to specific\\nfunctionality within a web application. URL routes programatically present\\nspecific content to users based on the URL that they are visiting. It is a\\npopular approach that has proven to be very effective.\"), mdx(\"p\", null, \"Something that might not be obvious is that URL routing is also a \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://en.wikipedia.org/wiki/Finite-state_machine\"\n  }, \"finite state\\nmachine\"), \". When you configure\\nthe routing for an app, you are laying out the various states the application\\ncan be in, and informing the application what to display and do when a specific\\nroute is encountered.\"), mdx(\"p\", null, \"AngularJS supplies \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://docs.angularjs.org/tutorial/step_07\"\n  }, \"URL routing\"), \" by default.\\nIt is adequate, but also has some limitations.\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"698px\"\n    }\n  }, \"\\n      \", mdx(\"a\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-link\",\n    \"href\": \"/static/357889ed147e92c9c2de25ee1ed3e09c/487bb/app-layout.png\",\n    \"style\": {\n      \"display\": \"block\"\n    },\n    \"target\": \"_blank\",\n    \"rel\": \"noopener\"\n  }, \"\\n    \", mdx(\"span\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"56.75675675675676%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABSElEQVQoz6WQXU+DQBBF+f+/yPiqUV9Mo6ILi/YDCsuyzOxuKbBtZcdgebBa44PJebi5ycmdTPC6vk8xXMHTBIYLCJf4nJSzq9nF9cPlm3pcQPiTlXoKXrJFVJtIQaQwqjXLC12um1raSsjVUqbLjSrPIVGmAcsrviGuPTfELTHR7CtL5kB6R/Ywhe840genIGC55IZieI9h4IZYYXcVku48th7bAbYDbD0cQ3ssPbaEXa/UuJxYmjd+vqXEEis2n3JP2I3onpoDGUebPdndVI64UY4KxWp/G5U3sWAwMDHJHloyri+wjBZNWime4rwYy9Fsv8jg75LqjKz7vkAZL5tMqSQ7I//r7FE2xHHg6BNDkTiVofPHP8H0p5PlMJMMiYFnQAwpXFtXIoHzdfc7LdWukyrI5EpYLUwtDAiDRS06zJ0p/6Qz+QfPE2U/NeO1pAAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"img\", {\n    parentName: \"a\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"alt\": \"A resonable application structure\",\n    \"title\": \"A resonable application structure\",\n    \"src\": \"/static/357889ed147e92c9c2de25ee1ed3e09c/487bb/app-layout.png\",\n    \"srcSet\": [\"/static/357889ed147e92c9c2de25ee1ed3e09c/a2ead/app-layout.png 259w\", \"/static/357889ed147e92c9c2de25ee1ed3e09c/6b9fd/app-layout.png 518w\", \"/static/357889ed147e92c9c2de25ee1ed3e09c/487bb/app-layout.png 698w\"],\n    \"sizes\": \"(max-width: 698px) 100vw, 698px\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    },\n    \"loading\": \"lazy\",\n    \"decoding\": \"async\"\n  }), \"\\n  \"), \"\\n    \")), mdx(\"h2\", null, \"So what's the problem?\"), mdx(\"p\", null, \"Looking at the structure above, imagine an application where interacting with\\nitems on the header or the sidebar causes the main content to load completely\\ndifferent HTML. AngularJS provides a mechanism for this with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ng-switch\"), \". You\\ncan see a (very simple) example of this below.\"), mdx(\"iframe\", {\n    width: \"100%\",\n    height: \"300\",\n    src: \"https://jsfiddle.net/joelhooks/Swm48/4/embedded/result,js,html\",\n    allowFullScreen: \"allowfullscreen\",\n    frameBorder: \"0\"\n  }), mdx(\"p\", null, \"In this case, \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ng-switch\"), \" is swapping out \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"div\"), \" elements, but you can also use\\nthis approach to swap out templates using \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ng-include\"), \".\"), mdx(\"p\", null, \"I'm not going to explore this option. I'm not particularly fond of it.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Why not?\")), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"The \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"ng-switch\"), \" adds markup that could be confusing\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"The state of the main content area is captured and stored on a model\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"It feels like \\\"logic in markup\\\", which I try to avoid\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"If you go down the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"ng-include\"), \" road, you need to remember to always put\\nsingle quotes around your template names. I always forget. ;<\")), mdx(\"h2\", null, \"ui-router\"), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/angular-ui/ui-router\"\n  }, \"ui-router\"), \" fully embraces the\\nstate-machine nature of a routing system. It allows you to define states, and\\ntransition your application to those states. The real win is that it allows you\\nto decouple nested states, and do some very complicated layouts in an elegant\\nway.\"), mdx(\"p\", null, \"You need to think about your routing a bit differently, but once you get your\\nhead around the state-based approach, I think you will like it.\"), mdx(\"iframe\", {\n    width: \"100%\",\n    height: \"300\",\n    src: \"https://jsfiddle.net/SvUjA/1/embedded/result,js,html\",\n    allowFullScreen: \"allowfullscreen\",\n    frameBorder: \"0\"\n  }), mdx(\"p\", null, \"This example is functionally very similar to the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ng-switch\"), \" approach. The main\\ndifference is that the main content area is populated with templated HTML for\\neach of the states, without using switching or \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ng-include\"), \".\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"angular.module('app', ['ui.compat']).config([\\n  '$stateProvider',\\n  function($stateProvider) {\\n    var home = {\\n        name: 'home',\\n        url: '/',\\n        templateUrl: 'content.html',\\n      },\\n      red = {\\n        name: 'red',\\n        url: '/red',\\n        parent: home,\\n        templateUrl: 'content.red.html',\\n      },\\n      blue = {\\n        name: 'blue',\\n        url: '/blue',\\n        parent: home,\\n        templateUrl: 'content.blue.html',\\n      },\\n      green = {\\n        name: 'green',\\n        url: '/green',\\n        parent: home,\\n        templateUrl: 'content.green.html',\\n      };\\n\\n    $stateProvider.state(home);\\n    $stateProvider.state(red);\\n    $stateProvider.state(green);\\n    $stateProvider.state(blue);\\n  },\\n]);\\n\")), mdx(\"p\", null, \"The above code is the configuration for the router. We are defining the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"module\"), \", but instead\\nof injecting \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"$routeProvider\"), \" as we would with stock AngularJS, we are injecting\\na \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"$stateProvider\"), \" that is used to define the states. We are defining 4 states.\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"home\"), \" is the parent state of the next 3. It defines the header, siderbar, and\\nthe \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"ui-view\"), \" element that will be populated with the child states.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"red\"), \" is the first child state. It references the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"home\"), \" as its parent, as\\nwell as targeting its own template.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"blue\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"green\"), \" are identical to \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"red\"), \", but use different templates.\")), mdx(\"p\", null, \"After the states are defined, they are added to the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"$stateProvider\"), \". They are\\nnow ready to be navigated to.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"    .run(['$state', function ($state) {\\n       $state.transitionTo('home');\\n    }])\\n\")), mdx(\"p\", null, \"the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"run\"), \" method is a great place to navigate to your intial state. You are able to\\ninject the now-resolved \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"$state\"), \" object and use its \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"transitionTo\"), \" method to set \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"home\"), \"\\nas the current state.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"    .controller('SidebarCtrl', function ($scope, $state) {\\n\\n    $scope.content = ['red', 'green', 'blue'];\\n\\n    $scope.setPage = function (page) {\\n        $state.transitionTo(page);\\n    };\\n\")), mdx(\"p\", null, \"The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"SidebarCtrl\"), \" lists contains a simple array called content on its \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"$scope\"), \" which\\nis used in a \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ng-repeat\"), \" to give us a simple menu. When one of those items is clicked\\nthe \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"setPage\"), \" function is called with the item that was clicked. In this case, the\\ncontent items correspond to the names of the states that we've defined, so we simply\\n\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"transitionTo\"), \" the selected state to display the content of that state.\"), mdx(\"h2\", null, \"Next steps with ui-router\"), mdx(\"p\", null, \"This only really scratches the very surface of what you can pull off with\\nui-router. There are a ton of options and the\\n\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/angular-ui/ui-router/wiki\"\n  }, \"wiki\"), \" is well put together. Some\\nthings I didn't explore, but that are available:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Passing data between states\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Listening for state events\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Named views (love this, it deserves its own post)\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"URL Routing\")), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"The ui-router README warns that the utility is still in active early\\ndevelopment\"), \". The API is still subject to change, so if you choose ui-router for\\nyour next project, that is something to be aware of.\"), mdx(\"p\", null, \"Let me know if you'd like me to explore ui-router a bit deeper in future posts.\\nI think it is an excellent approach to routing, and look forward to using it\\nmore.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Update:\"), \" I've recorded a \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://egghead.io/lessons/angularjs-introduction-ui-router\"\n  }, \"screencast about ui-router\"), \" for egghead.io.\"), mdx(\"p\", null, mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"Update 2:\"), \" Here's a \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://egghead.io/lessons/angularjs-ui-router-named-views\"\n  }, \"screencast about ui-router's named views\"), \" that I recorded for egghead.io. (note: it is paid/subscription content)\"));\n}\n;\nMDXContent.isMDXComponent = true;","frontmatter":{"title":"The basics of using ui-router with AngularJS","date":"July 22, 2013","banner":null,"slug":null,"keywords":null}}},"pageContext":{"id":"d8b08354-1165-5dda-8006-e759a1c70551","prev":{"id":"f5ef54ec-a963-578e-b926-4ff1ab6100df","parent":{"name":"2013-07-29-using-angularjs-stop-using-jquery-as-a-crutch","sourceInstanceName":"legacy"},"excerpt":"Have you ever heard (or said!) this: \"Directives? That's where the jQuery goes.\" I definitely have. In an effort to better understand\n @joshdmiller 's excellent\n ng-boilerplate , I\nwanted to understand its dependency on Boostrap. More specifically, I…","fields":{"title":"Using AngularJS? Stop using jQuery as a crutch.","slug":"blog/2013/07/27/using-angularjs-stop-using-jquery-as-a-crutch","date":"2013-07-27T00:00:00.000Z"}},"next":{"id":"7e74f129-d4c3-51f2-86f1-8b100280395f","parent":{"name":"2013-07-15-a-look-at-angularjs-internal-directives-that-override-standard-html-tags","sourceInstanceName":"legacy"},"excerpt":"Directives are the heart and soul of AngularJS. They are incredibly powerful.\nAngularJS sets out to extend the grammar of the browser to supply semantics that\nfacilitate the creation of web applications, going beyond the standard\nhyper-linked web…","fields":{"title":"AngularJS Directives That Override Standard HTML Tags","slug":"blog/2013/07/15/a-look-at-angularjs-internal-directives-that-override-standard-html-tags","date":"2013-07-15T00:00:00.000Z"}}}},
    "staticQueryHashes": ["1045846374"]}