Tag Archives: angularjs

AngularJS When processing the DOM takes a long time

You already know that you can add a progress spinner when an asynchronous process takes a long time. For example, say you’re loading data from a REST call.

$http.get(url)
  .then(function(res) {
    $scope.data = res.data;
  });

<div ng-hide="data">
  <i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
</div>

<div ng-show="data">
  {{data}}
</div>

But let’s say you need to reload that data, like paging. And suppose the data is HUGE and it takes a really long time for the DOM to be updated even if you already have the data in memory. What happens is that when you initiate action, the page seems to stall with the old data still there. This is bad UI because it makes the user feel like nothing is happening and may cause them to click around.

Ideally, you want the old data to be cleared so that the spinner can appear again. But clearing the data before setting it won’t do what you’d expect.

function() {
  $scope.data = null;
  $scope.data = ...
}

What happens here is that $scope.data is set to null, then to the new data, but the page will not change until the new data is painted and ready to show to the user. Why didn’t setting $scope.data to null immediately make the spinner appear?

Angularjs only sees the changes at the end of the function. Form Angular’s view, $scope.data went from the old data to the new. It never saw the update to null.

Here’s how I get around that.

function() {
  $scope.data = null;

  setTimeout(function() {
    $scope.$apply(function() {
      $scope.data = ...
    })
  }, 100)
}

In the main thread of the code, I set $scope.data to null. Then I create a 2nd thread with the setTimeout() which is asynchronous, so the function ends and angularjs updates. It now sees that $scope.data is null so it erases the DOM and shows the spinner.

Eventually, the timer kicks off (set for 100ms in this case), and it applies the function that sets $scope.data to the new data. While this is happening and the DOM is painted in the background, the user sees the spinning icon. Once it’s complete, the spinner goes away and the data is shown.

Advertisements
Tagged

Angular: Controls between parent and directives

If you need the parent controller to call a directive’s scope function, then this is how you need to set everything up. Stackoverflow

If you need a directive to call the parent’s scope function, then this is how you set them up. Stackoverflow

Tagged

Tomcat ContextPath and Angularjs

An interesting obstacle arose when I tried to use Angularjs (NG) in Tomcat, specifically in regards to the path.

Typically, I’ve been using NG assuming everything starts at the root path. So my index.html is at http://domain.com/index.html.

However, in Tomcat, each webapp has its own starting path. So you may have a weather webapp that is at http://domain.com/weather/ and a clock webapp at http://domain.com/clock/.

How do you configure NG within tomcat?

You could hardcode your starting path. But imagine if you wanted to have two clock webapps in tomcat, renaming one to http://domain.com/clock1/ and the other http://domain.com/clock2.

Now you would have to change all the references of “clock” to “clock1” and “clock2” respectively. And there are many references…

In the index.html, you have to change all your <link …css> as well as all <script …js>. You might think that you can outsmart yourself by changing the index.html to a index.jsp and using <%=request.getContextPath()%>.

But then you still have to change references of the hardcoded path in your .js files, such as your app.js that defines your module and routes.

And don’t even get me started on all your templates that reference .js and .css.

Well, let me jump straight to the short answer.

In your index.html, simply add this within your <head> tag

<head>
    <base href="/clock/" />
</head>

That’s it. Now all your relative paths will have that base href prefixed to them automatically.

So <link href=”mystyle.css”> will automatically fetch from http://domain.com/clock/mystyle.css

<script src=”myscripts.js>” will automatically fetch from http://domain.com/clock/myscripts.js

Even app.js will leverage this base when using relative url’s.
e.g. $routeProvider.when(‘/’, {templateurl: ‘home.html’})
will automatically reference http://domain.com/clock/home.html

This html standard can even be used on jsp pages. Anything that is html will take advantage of it

Tagged , , ,