{"id":4949,"date":"2015-06-04T00:19:23","date_gmt":"2015-06-03T21:19:23","guid":{"rendered":"http:\/\/www.webcodegeeks.com\/?p=4949"},"modified":"2015-05-28T00:27:14","modified_gmt":"2015-05-27T21:27:14","slug":"angularjs-project-essentials","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/","title":{"rendered":"AngularJS Project Essentials"},"content":{"rendered":"<p>You\u2019ve read the tutorials, watched the online demos and wrote the to-do list app in Angular. Now you\u2019ve been assigned your first real world project. You create the project, hook in Angular, and start coding away.<\/p>\n<p>\u201cNow what?\u201d<\/p>\n<p>After over three years of writing Angular enterprise apps, I\u2019ve found there are a few elements I almost always pull in. I hesitate to call these \u201cbest practices\u201d because they are common but not universal, and they are too small to really justify releasing as part of a stand-alone module, so I\u2019ve gathered them here in a single blog post to share with you.<\/p>\n<h2>An ng-View to a Kill<\/h2>\n<p>When you write apps that fetch large amounts of data or that load dozens of components, it quickly becomes clear the user experience isn\u2019t as clean \u201cout of the box\u201d as you might want it to be. If you\u2019ve seen the \u201cflicker\u201d caused by rendering a screen full of moustaches you know what I mean. There is no reason the end user should ever have to see:<\/p>\n<p>{{model.foo}}<\/p>\n<p>Flicker briefly before turning into some text.<\/p>\n<p>Angular provides <a href=\"https:\/\/docs.angularjs.org\/api\/ng\/directive\/ngCloak\" target=\"_blank\">ngCloak<\/a> as a way to manage this, but I\u2019ve found an even more straightforward approach. Most of my projects include <a href=\"http:\/\/getbootstrap.com\/\" target=\"_blank\">Bootstrap<\/a> which has a nice set of styles for showing and hiding portions of the UI. Although I <a href=\"http:\/\/csharperimage.jeremylikness.com\/2014\/08\/no-need-to-watch-angularjs-controller-as.html\" target=\"_blank\">preach the use of controller as<\/a> I\u2019m not opposed to using the <a href=\"https:\/\/docs.angularjs.org\/api\/ng\/service\/$rootScope\" target=\"_blank\">$rootScope<\/a> goo that makes a nice cork board to pin UI behaviors on.<\/p>\n<p>Take a look at this approach:<\/p>\n<pre class=\" brush:php\">\r\n&lt;div class=\"container body-content hide\"  \r\n        ng-class=\"{'show': loaded}\"  \r\n        ng-init=\"loaded=true\"  \r\n        ng-app=\"myApp\"&gt;\r\n<\/pre>\n<p>The content is rendered as hidden out of the gate. A conditional class to show the content is applied based on a variable that will only exist once the application is initialized. It\u2019s simple, clean, and doesn\u2019t require testing or exposing strange controller methods just to handle a common UI behavior.<\/p>\n<h2>Animations for the Design-Challenged<\/h2>\n<p>I\u2019m not much of a designer or animator. I make an effort to keep up to date and consistently force myself outside of my comfort zone, but I\u2019m a long way from architecting my own master CSS or creating a super cool animation from scratch. That\u2019s why I\u2019ve made friends with two cool libraries. The first, part of Angular, is called <a href=\"http:\/\/www.nganimate.org\/\" target=\"_blank\">ngAnimate<\/a>.<\/p>\n<p>Apparently there is a lot you can do with this, but I stop at including it as a dependency. That\u2019s because I also depend on my other friend, <a href=\"http:\/\/daneden.github.io\/animate.css\/\" target=\"_blank\">animate.css<\/a>. With a little bit of my own CSS, I can introduce the two to each other and implement all of the transitions I would ever care to use.<\/p>\n<p>Here\u2019s two examples that I crafted in my custom CSS to layer on top of the built-in styles that Bootstrap provides.<\/p>\n<pre class=\"brush:css\">\r\ndiv[ng-view].ng-enter {\r\n    -webkit-animation: zoomIn 0.1s, pulse 0.5s;\r\n    animation: zoomIn 0.1s, pulse 0.5s;\r\n}\r\n \r\n.alert.ng-enter {\r\n    -webkit-animation: slideInUp 0.3s;\r\n    animation: slideInUp 0.3s;\r\n}\r\n<\/pre>\n<p>The first zooms and pulses new pages when the user navigates using Angular\u2019s built-in router, and the other causes alerts to magically slide up to their position. You get the point \u2013 by starting with Angular\u2019s classes, you can combine them with animations that will fire either globally or locally depending on how they are defined. The animations site itself is a great way to test and vet which animations you wish to use.<\/p>\n<h2>Give your Elements a Hand<\/h2>\n<p>While you\u2019re in your CSS you might as well add this one.<\/p>\n<pre class=\"brush:css\">\r\n.cursor-hand {\r\n    cursor: pointer;\r\n    cursor: hand;\r\n}\r\n<\/pre>\n<p>Have you ever bound an <a href=\"https:\/\/docs.angularjs.org\/api\/ng\/directive\/ngClick\" target=\"_blank\">ng-click<\/a> directive to an element that isn\u2019t normally a link? Isn\u2019t it weird that the cursor doesn\u2019t change when you hover over it? Apply the cursor-hand class and it will show a nice little indication that it\u2019s clickable, just like buttons and links do.<\/p>\n<h2>The Title is Yours<\/h2>\n<p>Have you ever found yourself running the same SPA application in multiple tabs, only to find navigation is a nightmare because they all have the same title? Give yourself, and your users, a break and update the title with context.<\/p>\n<p>Here\u2019s a tip: avoid the temptation to prefix the title with your app\u2019s name. Your users know they are using it and don\u2019t need the reminder. When most browsers become cluttered with tabs, the tabs shrink and you end up only seeing the app name portion of the title. Instead, put the most specific information <em>first<\/em> and if you like, append the title to the end.<\/p>\n<p>Instead of:<\/p>\n<p>My Bodybuilding App | Exercises | Inverted Squat<\/p>\n<p>Try:<\/p>\n<p>Inverted Squat | Exercises | My Bodybuilding App<\/p>\n<p>I also like to use a service for this. That way I can mock it for tests, but easily change the application name in one place or even enhance the service to log consumption. This is what I end up with in most projects:<\/p>\n<pre class=\" brush:php\">\r\nfunction service($window) {\r\n    this.$window = $window;\r\n    this.currentTitle = $window.document.title;\r\n}\r\n \r\nangular.extend(service.prototype, {\r\n    setTitle: function(title) {\r\n        var titleToSet = title + \" | The Best App Ever\";\r\n        this.$window.document.title = titleToSet;\r\n        this.currentTitle = titleToSet;\r\n\r\n    }\r\n});\r\n \r\napp.service(\"titleSvc\", [\"$window\", service]);\r\n<\/pre>\n<p>Feel free to use it in your own (by the way, I call this from the constructor but also whenever the context in a controller changes).<\/p>\n<h2>Getting Busy<\/h2>\n<p>Everyone likes a busy indicator, right? I usually create a modal dialog using bootstrap right at the top of my application:<\/p>\n<pre class=\" brush:php\">\r\n&lt;div class=\"modal modal-backdrop\" ng-class=\"{ show: isBusy }\"&gt;\r\n    &lt;div class=\"modal-body\"&gt;\r\n        &lt;div class=\"row center-block text-center h1\"&gt;\r\n            Give me a minute, OK?\r\n        &lt;\/div&gt;\r\n    &lt;\/div&gt;\r\n&lt;\/div&gt;\r\n<\/pre>\n<p>Next, I create a service. What\u2019s nice is the service will work across multiple requests, so if you are waiting on three services it will stay activated until the last one completes. Each component just calls setBusy() to kick things off and resetBusy() when ready. It also has a slight delay built in so you don\u2019t get flicker when the service loads quickly.<\/p>\n<pre class=\" brush:php\">\r\nfunction service($rootScope, $timeout) {\r\n    this.$rootScope = $rootScope;\r\n    this.$timeout = $timeout;\r\n    this.$rootScope.isBusy = false;\r\n    this.busyCount = 0;\r\n}\r\n \r\nangular.extend(service.prototype, {\r\n \r\n    setBusy: function () {\r\n        var that = this;\r\n        this.busyCount += 1;\r\n        this.$timeout(function() {\r\n            that.$rootScope.isBusy = !!that.busyCount;\r\n        }, 300);\r\n    },\r\n \r\n    resetBusy: function() {\r\n        this.busyCount -= 1;\r\n        this.$rootScope.isBusy = !!this.busyCount;  \r\n    }\r\n \r\n});\r\n \r\napp.service(\"busySvc\", [\"$rootScope\", \"$timeout\", service]);\r\n<\/pre>\n<p>Because I also like to save myself keystrokes, instead of calling this every time I am waiting on a web service, I simply plug it in globally using <a href=\"https:\/\/docs.angularjs.org\/api\/ng\/service\/$http#interceptors\" target=\"_blank\">interceptors<\/a>.<\/p>\n<pre class=\" brush:php\">\r\napp.config([\r\n    \"$provide\", \"$httpProvider\", function (provide, httpProvider) {\r\n \r\n        provide.factory(\"busyInterceptor\", [\"$q\", \"$injector\", function (q, injector) {\r\n                var getService = function() {\r\n                    return injector.get(\"busySvc\");\r\n                };\r\n                return {\r\n                    request: function(config) {\r\n                        getService().setBusy();\r\n                        return config || q.when(config);\r\n                    },\r\n                    response: function(response) {\r\n                        getService().resetBusy();\r\n                        return response || q.when(response);\r\n                    },\r\n                    responseError: function(rejection) {\r\n                        getService().resetBusy();\r\n                        return q.reject(rejection);\r\n                    }\r\n                };\r\n            }\r\n        ]);\r\n \r\n        httpProvider.interceptors.push(\"busyInterceptor\");\r\n    }\r\n]);\r\n<\/pre>\n<p>Then I rarely have to call it explicitly.<\/p>\n<h2>A Dirty Little Trick<\/h2>\n<p>Almost every app ends up with some complex form that has dozens of fields to fill out. No user wants to spend ten minutes filling out a form only to accidentally close the window or navigate away. I handle this scenario with a directive. The directive allows me to bind to whatever trigger should prompt the user before navigating. In most cases that is the state of a form, but the beauty of Angular and data-binding is that you can use whatever you like, whether it is an expression or a custom property you expose.<\/p>\n<p>Here is the directive, complete with the code to clean up after itself when the user does navigate away:<\/p>\n<pre class=\" brush:php\">\r\napp.directive('dirtyChecking', [\r\n    '$rootScope', '$window', function (rs, $window) {\r\n        return {\r\n            restrict: 'E',\r\n            replace: true,\r\n            template: '&lt;span&gt;&lt;\/span&gt;',\r\n            scope: {\r\n                dirty: '='\r\n            },\r\n            link: function (scope) {\r\n                var cleanUpFn = angular.noop, unwatch,\r\n                    checkScope = function() {\r\n                    if (scope.dirty) {\r\n                        cleanUpFn = rs.$on('$locationChangeStart', function(event) {\r\n                            if (!$window.confirm('You have unsaved changes, do you want to continue?')) {\r\n                                event.preventDefault();\r\n                            }\r\n                        });\r\n                    } else {\r\n                        cleanUpFn();\r\n                        cleanUpFn = angular.noop;\r\n                    };\r\n                }\r\n                unwatch = scope.$watch('dirty', checkScope);\r\n                scope.$on('$destroy', function() {\r\n                    cleanUpFn();\r\n                    unwatch();\r\n                });\r\n            }\r\n        }\r\n    }\r\n]);\r\n<\/pre>\n<p>And here it is in use:<\/p>\n<pre class=\" brush:php\">\r\n&lt;div ng-controller=\"myCtrl as ctrl\"&gt;\r\n    &lt;form name=\"ctrl.myForm\" novalidate=\"\"&gt;\r\n        &lt;dirty-checking dirty=\"ctrl.myForm.$dirty\"&gt;\r\n        &lt;\/dirty-checking&gt;\r\n<\/pre>\n<p>It\u2019s a dirty little trick but it works well!<\/p>\n<h2>You\u2019ve Been Alerted<\/h2>\n<p>The final pattern I implement in most apps is notifications or toasts. Bootstrap provides some very helpful classes for these. I typically create a simple service that hosts an array of alerts, then provides methods to add different types of alerts. I\u2019ll leave the implementation up to you, but here\u2019s where the tip comes in: in some cases you might be alerting an error when what you really want is to throw an exception. With a little configuration, you can intercept errors and alert on those as well. You can safely throw a new Error(\u201cOops!\u201d) and know the user will get feedback because you\u2019ve taken over.<\/p>\n<p>This one is easier to show, so you can <a href=\"http:\/\/jsfiddle.net\/jeremylikness\/ahxwrcu2\/\" target=\"_blank\">run it and view the source here<\/a>. Note the use of the property getter to refresh the alerts from the controller without having to rely on $scope or using a $watch. In this case I\u2019m passing the exception along to the default handler, but I could easily just swallow it in my replacement function as well.<\/p>\n<p>That\u2019s it for me. I\u2019m sure many of you reading this also have common snippets you use. Feel free to reply to the comments here to share your ideas, and as always your feedback and suggestions are welcome!<\/p>\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td><span class=\"reference\">Reference: <\/span><\/td>\n<td><a href=\"http:\/\/csharperimage.jeremylikness.com\/2015\/05\/angularjs-project-essentials.html\">AngularJS Project Essentials<\/a> from our <a href=\"http:\/\/www.webcodegeeks.com\/wcg\/\">WCG partner<\/a> Jeremy Likness at the <a href=\"http:\/\/csharperimage.jeremylikness.com\/\">C#er : IMage<\/a> blog.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>You\u2019ve read the tutorials, watched the online demos and wrote the to-do list app in Angular. Now you\u2019ve been assigned your first real world project. You create the project, hook in Angular, and start coding away. \u201cNow what?\u201d After over three years of writing Angular enterprise apps, I\u2019ve found there are a few elements I &hellip;<\/p>\n","protected":false},"author":40,"featured_media":909,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[25],"tags":[],"class_list":["post-4949","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-angular-js"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>AngularJS Project Essentials - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"You\u2019ve read the tutorials, watched the online demos and wrote the to-do list app in Angular. Now you\u2019ve been assigned your first real world project. You\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"AngularJS Project Essentials - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"You\u2019ve read the tutorials, watched the online demos and wrote the to-do list app in Angular. Now you\u2019ve been assigned your first real world project. You\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2015-06-03T21:19:23+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jeremy Likness\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/jeremylikness\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeremy Likness\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/\"},\"author\":{\"name\":\"Jeremy Likness\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/2cd31c082e3e1cc5f595ba18a6e03a43\"},\"headline\":\"AngularJS Project Essentials\",\"datePublished\":\"2015-06-03T21:19:23+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/\"},\"wordCount\":1308,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"articleSection\":[\"Angular.js\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/\",\"name\":\"AngularJS Project Essentials - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"datePublished\":\"2015-06-03T21:19:23+00:00\",\"description\":\"You\u2019ve read the tutorials, watched the online demos and wrote the to-do list app in Angular. Now you\u2019ve been assigned your first real world project. You\",\"breadcrumb\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"JavaScript\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/javascript\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Angular.js\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/javascript\/angular-js\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"AngularJS Project Essentials\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/2cd31c082e3e1cc5f595ba18a6e03a43\",\"name\":\"Jeremy Likness\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b4d8ee78925818e3f7a4d0d82df06d34a2b76aa4d260a1f4b67dc0553efbf1b6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b4d8ee78925818e3f7a4d0d82df06d34a2b76aa4d260a1f4b67dc0553efbf1b6?s=96&d=mm&r=g\",\"caption\":\"Jeremy Likness\"},\"description\":\"Jeremy Likness is a principal architect at iVision, Inc. He has been building enterprise applications using the Microsoft stack for 20 years with a focus on web-based solutions for the past 15. A prolific author and speaker, Jeremy's mission is to empower developers to create success in their careers through learning and growth.\",\"sameAs\":[\"http:\/\/csharperimage.jeremylikness.com\/\",\"http:\/\/linkedin.com\/in\/jeremylikness\",\"https:\/\/x.com\/https:\/\/twitter.com\/jeremylikness\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/jeremy-likness\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"AngularJS Project Essentials - Web Code Geeks - 2026","description":"You\u2019ve read the tutorials, watched the online demos and wrote the to-do list app in Angular. Now you\u2019ve been assigned your first real world project. You","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/","og_locale":"en_US","og_type":"article","og_title":"AngularJS Project Essentials - Web Code Geeks - 2026","og_description":"You\u2019ve read the tutorials, watched the online demos and wrote the to-do list app in Angular. Now you\u2019ve been assigned your first real world project. You","og_url":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2015-06-03T21:19:23+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","type":"image\/jpeg"}],"author":"Jeremy Likness","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/jeremylikness","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Jeremy Likness","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/"},"author":{"name":"Jeremy Likness","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/2cd31c082e3e1cc5f595ba18a6e03a43"},"headline":"AngularJS Project Essentials","datePublished":"2015-06-03T21:19:23+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/"},"wordCount":1308,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","articleSection":["Angular.js"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/","url":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/","name":"AngularJS Project Essentials - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#primaryimage"},"image":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","datePublished":"2015-06-03T21:19:23+00:00","description":"You\u2019ve read the tutorials, watched the online demos and wrote the to-do list app in Angular. Now you\u2019ve been assigned your first real world project. You","breadcrumb":{"@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/10\/angularjs-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/www.webcodegeeks.com\/javascript\/angular-js\/angularjs-project-essentials\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"JavaScript","item":"https:\/\/www.webcodegeeks.com\/category\/javascript\/"},{"@type":"ListItem","position":3,"name":"Angular.js","item":"https:\/\/www.webcodegeeks.com\/category\/javascript\/angular-js\/"},{"@type":"ListItem","position":4,"name":"AngularJS Project Essentials"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/2cd31c082e3e1cc5f595ba18a6e03a43","name":"Jeremy Likness","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b4d8ee78925818e3f7a4d0d82df06d34a2b76aa4d260a1f4b67dc0553efbf1b6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b4d8ee78925818e3f7a4d0d82df06d34a2b76aa4d260a1f4b67dc0553efbf1b6?s=96&d=mm&r=g","caption":"Jeremy Likness"},"description":"Jeremy Likness is a principal architect at iVision, Inc. He has been building enterprise applications using the Microsoft stack for 20 years with a focus on web-based solutions for the past 15. A prolific author and speaker, Jeremy's mission is to empower developers to create success in their careers through learning and growth.","sameAs":["http:\/\/csharperimage.jeremylikness.com\/","http:\/\/linkedin.com\/in\/jeremylikness","https:\/\/x.com\/https:\/\/twitter.com\/jeremylikness"],"url":"https:\/\/www.webcodegeeks.com\/author\/jeremy-likness\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/4949","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/40"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=4949"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/4949\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/909"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=4949"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=4949"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=4949"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}