Common Angular Issues & their Solutions – Now Deal like a Pro

By Saurabh Barot   |   18 September, 2019
Common Angular Issues & their Solutions – Now Deal like a Pro

When it comes to creating a single page application, Angular comes first in the mind of every developer. As we all know that, there have been a great benefits of using Angular framework for your projects or you can say the web applications. However, there are some common and preventable issues occur at the time of development, if you are not attentive enough.

No, I am not talking about CSS and HTML, in fact, they are no longer the biggest concern. You have plenty of things to keep in mind at the time of development such as handling XHRs, application logic (which involves models, views, and controllers), performance, animations, SEO, integration, and so much more.

Why these things are so important…?

They are important to get the best result as far as the seamless user experience is concerned. Obviously, when we develop web application on Angular, the UX (User Experience) prioritized. And, Angular, being a very powerful framework and the third most starred repository on GitHub, is all meant to provide the extraordinary User Experience.

But, even after having the extraordinary framework at place and being expertise in the technologies, things do not go right as expected…

The reason is simple: there are some common mistakes which even an expert is supposed to commit, mostly unknowingly. Learning Angular is easy, but achieving the goal out of it requires good shares of comprehension, experience and expertise. So, we are here with acute researches, expert advice, suggestion and avoidable error that you can easily follow to escape them. Let’s embrace it!

Not Using Dot (-) in ngModel

Using ngModel without dot (-) is a mistake, we all know it very well, but do we follow it? Of course not, at least not by all. We all know that scope follow prototypal model of inheritance which is typical to JavaScript. At the same time, nested scopes are not special, but very common to Angular. ngRepeat, ngIf, and ngController these are child scopes, are created by directives. And, when we try to find a solution to resolve the model, the search or lookup begins with current scope and then to parent scope.

When you set a new value, the model will not set to current scope and it will prevent masking as well. Here’s how it happens;

function MainController($scope) {
  $scope.foo = 1;
  $scope.bar = {innerProperty: 2};
}
angular.module('myApp', [])
.controller('MainController', MainController);
<div ng-controller="MainController">
  <p>OUTER SCOPE:</p>
  <p>{{ foo }}</p>
  <p>{{ bar.innerProperty }}</p>
  <div ng-if="foo"> <!— ng-if creates a new scope —>
    <p>INNER SCOPE</p>
    <p>{{ foo }}</p>
    <p>{{ bar.innerProperty }}</p>
    <button ng-click="foo = 2">Set primitive</button>
    <button ng-click="bar.innerProperty = 3">Mutate object</button>
  </div>
</div>

How Do You Use Controller -As Syntax or Something Else?

Not using controller as syntax can create some issues with Angular application. However, to do it you need to assign model to use controller instead of injected scope.
When we don’t use controller as syntax, then things become complicated. Here’s how it creates hassle;

<div ng-app="app" ng-controller="SiteController">
  <!-- we are pretty sure we are getting the title from the SiteController -->
  <h1>{{title}}</h1>
    <div ng-controller="PersonController">
        <!-- is this the title from SiteController or PersonController? 
        is there even a title in both? -->
        <h2>{{title}}</h2>
    	<div ng-repeat="person in PersonCtrl.people">
        	<span>{{person.name}}</span>
      	</div>
    </div>
</div>

However, using controller as syntax can make things stunning!

Here’s how you can make it happen.

// site.controller.js:
(function() {
  'use strict';
  angular.module('app').controller('SiteController', SiteController);
  // no need to inject $scope because we don't need it
  SiteController.$inject = [];
  function SiteController() {
        // assigning this to a loacal variable makes it easier to 
        // declare properties and methods in the controller
    	var vm = this;
        // declare our title on this
        vm.title = "Welcome!";
  }

})();

// other.controller.js:
(function() {
  'use strict';
  angular.module('app').controller('OtherController', OtherController);
  function OtherController() {

    	var vm = this;
        vm.title = "Other title!";
  }
})();

Now you can see how simple and visible it becomes. Let’s explore how and where the data comes from.

<div ng-app="app" ng-controller="SiteController as SiteCtrl">
    <!-- we can be sure we are getting the title from the SiteController -->
  <h1>{{SiteCtrl.title}}</h1>
    <div ng-controller="OtherController as OtherCtrl">
        <!-- we can be sure we are getting the title from the OtherCtrl -->
        <h2>{{OtherCtrl.title}}</h2>
    </div>
</div>

Codepen Demo:

See the Pen
AngularJS Controller as syntax
by Christopher Northfield (@cnorthfield)
on CodePen.

Why Don’t You Use Named Views With UI-ROUTER For Power

Using Named ui-view enables you to have as many as needed ui-view per template. You use the following structure to make it happen.

<body>
  <header>
    <!-- SOME STATIC HEADER CONTENT -->
  </header>
  <section class="main">
    <div class="page-content">
    <div class="row">
      <div class="col-xs-12">
        <section class="intro">
          <h2>SOME PRODUCT SPECIFIC INTRO</h2>
        </section>
      </div>
    </div>
    <div class="row">
      <div class="col-xs-3">
        <section class="widget">
          <!-- some widget, which should never reload -->
        </section>
      </div>
      <div class="col-xs-9">
        <section class="content">
          <div class="product-content">
          <h2>Product title</h2>
          <span>Context-specific content</span>
        </div>
        </section>
      </div>
    </div>
  </div>
  </section>
  <footer>
    <!-- SOME STATIC HEADER CONTENT -->
  </footer>
</body>

You can separate them into file state with the following the structure;

<!— index.html —>
<body>
  <div ui-view></div>
</body>
<!— main.html —>
<header>
  <!-- SOME STATIC HEADER CONTENT -->
</header>

<section class="main">
  <div ui-view></div>
</section>

<footer>
  <!-- SOME STATIC HEADER CONTENT -->
</footer>

The products index will be something like this;

<div class="page-content">

  <div class="row">
    <div class="col-xs-12">
      <section class="intro">
        <div ui-view="intro"></div>
      </section>
    </div>
  </div>

  <div class="row">
    <div class="col-xs-3">
      <section class="widget">
        <div ui-view="widget"></div>
      </section>
    </div>
    <div class="col-xs-9">
      <section class="content">
        <div ui-view="content"></div>
      </section>
    </div>
  </div>
</div>

We have given three ui-view for separate index page: the first one belongs to intro, second for widget and third is dedicated to product.

function config($stateProvider) {
  $stateProvider
    // MAIN ABSTRACT STATE, ALWAYS ON
    .state('main', {
      abstract: true,
      url: '/',
      controller: 'MainController as MC',
      templateUrl: '/routing-demo/main.html'
    })
    // A SIMPLE HOMEPAGE
    .state('main.homepage', {
      url: '',
      controller: 'HomepageController as HC',
      templateUrl: '/routing-demo/homepage.html'
    })
    // THE ABOVE IS ALL GOOD, HERE IS TROUBLE
    // A COMPLEX PRODUCT PAGE
    .state('main.product', {
      abstract: true,
      url: ':id',
      controller: 'ProductController as PC',
      templateUrl: '/routing-demo/product.html',
    })
    // PRODUCT DEFAULT SUBSTATE
    .state('main.product.index', {
      url: '',
      views: {
        'widget': {
          controller: 'WidgetController as PWC',
          templateUrl: '/routing-demo/widget.html' 
        },
        'intro': {
          controller: 'IntroController as PIC',
          templateUrl: '/routing-demo/intro.html' 
        },
        'content': {
          controller: 'ContentController as PCC',
          templateUrl: '/routing-demo/content.html'
        }
      }
    })
    // PRODUCT DETAILS SUBSTATE
    .state('main.product.details', {
      url: '/details',
      views: {
        'widget': {
          controller: 'WidgetController as PWC',
          templateUrl: '/routing-demo/widget.html' 
        },
        'content': {
          controller: 'ContentController as PCC',
          templateUrl: '/routing-demo/content.html'
        }
      }
    });
}
angular.module('articleApp', [
  'ui.router'
])
.config(config);

Now, switching between main.product.index and main.product.details would reload content and "widget get", but what if we want to reload on the content? There were various tricks created but none satisfied developers at large until ui-router came into light.

// A COMPLEX PRODUCT PAGE
// WITH NO MORE TROUBLE
.state('main.product', {
  abstract: true,
  url: ':id',
  views: {
    // TARGETING THE UNNAMED VIEW IN MAIN.HTML
    '@main': {
      controller: 'ProductController as PC',
      templateUrl: '/routing-demo/product.html' 
    },
    // TARGETING THE WIDGET VIEW IN PRODUCT.HTML
    // BY DEFINING A CHILD VIEW ALREADY HERE, WE ENSURE IT DOES NOT RELOAD ON CHILD STATE CHANGE
    'widget@main.product': {
      controller: 'WidgetController as PWC',
      templateUrl: '/routing-demo/widget.html' 
    }
  }
})
// PRODUCT DEFAULT SUBSTATE
.state('main.product.index', {
  url: '',
  views: {
    'intro': {
      controller: 'IntroController as PIC',
      templateUrl: '/routing-demo/intro.html' 
    },
    'content': {
      controller: 'ContentController as PCC',
      templateUrl: '/routing-demo/content.html'
    }
  }
})
// PRODUCT DETAILS SUBSTATE
.state('main.product.details', {
  url: '/details',
  views: {
    'content': {
      controller: 'ContentController as PCC',
      templateUrl: '/routing-demo/content.html'
    }
  }
});

There are some other way as well that you need to explore.

Code Organization

Keeping code organized in logical manner is as important as developing an app for your venture. It not just let you find the important files easily, but also makes plenty of other things like smooth performance, uses. As the code expands, number of files increases, and more number of controllers and services added, then your app is supposed to become bloated to point of incoherence. Things like locating simple files will become complex while in larger projects, it may create a lot of overlap between modules and shared common code. So, code organization is important to look after, in this case. Here’s you can begin with;

Create workspace with Angular CLI ng new command

ng new <my-project>

When you run this command, all necessary npm packages will be created.

WORKSPACE CONFIG FILES PURPOSE
.editorconfig Configuration for code editors
.gitignore What Git ignore, it specifies (the files)
README.md The root app will have introductory documentation
angular.json Default CLI configuration for all projects
package.json To configure dependencies and more
package-lock.json Version information for all packages
src/ Crate source file for root level application
node_modules/ For npm packages for the entire workspace
tsconfig.json For TypeScript configuration by default
tslint.json TSLint configuration for projects in the workspace by default

Besides, there are some other things which you can do make the project more easy and findable.

  • Create archetypes directory
  • Segregate objects to defined or into own files
  • For modules, you can follow the same set of rules such as;
  • Creating a directory for shared code
  • Segregating modules into submodules

Loading JavaScript Files

The AngularJS projects with hundreds of JavaScript files will impact heavily on site performance. The problem could be visible when you load files upfront in your shell page –the page you are currently on. It is inevitable as the large Angular project with large number of JS files will not be loaded simultaneously. It will done one by one while it is possible that they may dependent on other JavaScript files too.

To escape such issue, loading JavaScript files dynamically is the right options (dynamic loading) as Angular will split the code separate modules which will make an easy way to load files asynchronously. Let’s understand this from the tips here;

Yes, you read it right: all you need to do is call the service load method with keys of the scripts you want to load in DashboardComponent
Let me show you how:

Open your Network panel and go to the Home Page of your application. You won’t see the chart.js script being fetched.

Now, try opening the Dashboard view and you’ll see a request is sent to chart.js CDN.

That’s it, your job is done.

Angular Issue with Debugging Code

Debugging is the most important thing as problems are sure to occur with any projects. Some of them would be even difficult to debug but using some of the most used and successful chrome extension or tools, you can do it easily. Here’s a few of them;

Angular JS Batarang

A extremely important and useful Chrome extension for debugging which simplifies the debugging by allowing you to request further information and choose the section you want to view for debug.

Dependency Graph

Dependency Graph is important as you can know the dependencies between components. It becomes even more important when you try understanding the project or app working. You can easily find any error, if occurred in part of the project and cure them quickly.

Performance Tool

It is just another tool which allows you to introspect about the function and how much it takes to execute the action. In case, you get any error, you can fix them to function proper. It will lead your web app to run faster and smoother.

Angular Development Services
Final Words
Last but not least, mistakes are bound to happen, no matter how expertly the app has been built. However, keeping an eye over the common issue will help you escape such error easily. There are plenty of ways to do away with such issues. You can write to us what more you want to know from us so that we can provide more comprehensive solutions. At the same time, if you have any creative ways to come over with common issues with Angular Application, then we would appreciate your time to write to us.

Saurabh Barot

Saurabh Barot is co-founder and Experienced Chief Technology Officer at Aglowid IT Solutions. His deep industry experience in Angular, React, Ruby on Rails, PHP, Mean Stack and just to name few, has helped the company reach to a new level. He believes that technology is all about exploring new possibilities. Whatever a mind can think (exception can't be ruled out), technology brings it into reality.

Related Posts