Technology, Continued...

Ramblings about business, technology, development and my life

Using an Angular2 component with Angular1

Ok, so you have an Angular1 application, but you want to start building Angular2 components to use within the application.  Nothing like getting ahead of the upgrade game, right?  Well, follow the steps below and you’ll see that it’s not as hard as it might at first seem!

First, let me show you my project structure (this example is short and sweet – it’s not meant to be representative of a production app from a code organization perspective!).  I’ve stripped away everything I could from the example to make sure the focus was solely on making Angular2 components work inside an Angular1 application.

Project structure

image

AngularV1 code

Inside my app folder, first of all I have my angularv1 code.

image

All this code is doing is creating my app module and adding a controller to it.  However, do note that I’m injecting a module called ‘a2’ into the app.  More on this in a sec.

AngularV2 component code

Next, I have a basic AngularV2 component that is going to do nothing but accept a person object as an input and display a simple message using the first and last name of the person.

image

Using UpgradeAdapter to use Angular2 component from Angular1

Finally, the upgrade.ts file has the code that adds the V2 component to an Angular1 module called a2 that can then be injected into my Angular1 app, as shown above when creating my Angular1 module.

image

Bootstrapping your Angular1 app

Note that you can’t use ng-app to bootstrap your Angular1 application when using Angular2 alongside it.  Instead, you have to use the upgrade adapter’s bootstrap method.  This ensures that the Angular2 components are loaded along with the Angular1 application.

The index.html page

Setting up your index.html file is actually pretty simple.  First, load the Angular1 libraries and the Angular1 code file.  Next, load the Angular2 modules.

Note that I’m using SystemJs, so I import the app package which in turn causes my upgrade.ts file to load.

Finally, inside my Angular1 ng-controller directive which loads my V1Controller, I display the person properties, but I also load the Angular2 component and pass the person object to it as well.  Note that there is no ng-app directive.  As mentioned above, the upgrade adapter’s bootstrap method takes care of loading the Angular1 app.

image

It works

And, it works!  Here’s a screenshot.

image

systemjs.config.js

For reference, here’s my systemjs.config.js file

image

package.json

And here’s my package.json file.  Note I’m using npm rather than bower to install the necessary server and client libraries for my example.

image

That’s all, folks

So there you go.  Without too much effort you can start writing Angular2 components and using them in your existing Angular1 app!

Ng-repeat-start and ng-repeat-end with a child collection

If you have multiple table rows you want to create for each item in a collection you’re enumerating through with ng-repeat, you have to use special directives to do so.  Here’s what most people try first:

<div ng-repeat="item in col">
    <tr>
        <td>{{ item.name }}</td>
    </tr>
    <tr>
        <td>{{ item.description }}</td>
    </tr>
</div>

However, this doesn’t work, because trs can’t be contained in a div.  Fortunately, Angular 1.2 added the directives ng-repeat-start and ng-repeat-end for just this reason.  Instead of the above, you can do it this way:

<tr ng-repeat-start="item in col">
    <td>{{ item.name }}</td>
</tr>
<tr ng-repeat-end>
    <td>{{ item.description }}</td>
</tr>

This basically gives you a compound repeater where you can contain multiple sibling elements within the repeat.

One interesting situation I ran into was where I needed to also repeat a child collection of item above, within the col repeat.  Fortunately, you can combine ng-repeat-start/ng-repeat-end and ng-repeat on the same element, as shown below.  The example here will show you the name of the item in the first row, and then give you rows for each child of the item.  This will be repeated for as many items and children as there are.

<tr ng-repeat-start="item in col">
    <td>{{ item.name }}</td>
</tr>
<tr ng-repeat-end ng-repeat="child in item.children">
    <td>{{ child.name }}</td>
</tr>

Hopefully this helps someone else out there.

Why you can use AngularJS (or not)…

So it seems to be the time of year for Angular bashing.  Isn’t that how it always is when a technology becomes more prominent than others (and how long will that last, anyway?)?  The latest is this article about why you should not use AngularJS.

https://medium.com/@mnemon1ck/why-you-should-not-use-angularjs-1df5ddf6fc99

This article comes on the heels of another very similar one from October about what’s wrong with AngularJS.

https://medium.com/este-js-framework/whats-wrong-with-angular-js-97b0a787f903

Better minds than me have already talked about the October article.  Here are Dan Wahlin and John Papa’s responses.

http://www.johnpapa.net/why-does-there-have-to-be-something-wrong-with-angularjs/

http://weblogs.asp.net/dwahlin/what%E2%80%99s-%E2%80%9Cright%E2%80%9D-with-angularjs

For the new one about why you should not use AngularJS, here is my (very) short and sweet response to it.

Two-way data binding

You’d have to pry two-way data binding from my cold, dead hands. Yes, you have to be cognizant of potential performance issues. Yes, sometimes you will have to do things to work around specific issues you might run into. I once had to create my own treeview control because another one I was trying to use had too many bindings and was very slow. So I created my own directive that worked for my needs and kept bindings to a bare minimum. You have to develop with an eye towards potential performance issues. But the productivity improvements from Angular’s two way data binding for developers, as well as the SOC between view and controller make this a tradeoff I’m willing to accept. But to just carte blanche say that Angular is slow as a general statement is ridiculous. Many serious, complicated production apps have been built with Angular. It has proven that it performs fine, as long as you keep performance in mind in your edge development cases. But keeping performance in mind is something we should not only do with Angular, but with service calls, with database designs, with third party api integration work, etc. Performance considerations should be a part of a developer’s DNA, regardless of platform and technology.

Dependency injection

Ok, so he doesn’t like the syntax and flexibility that Angular offers. Fair enough. But the technology itself is fine. Angular is an opinionated framework. He doesn’t like the opinion. But I have found uses for the difference between service and factory before, even if 99% of people never will. If someone wants to use one or the other all the time, they never need to concern themselves with the other options. But they’re there if you need them. As for syntax specifically, they worked around a problem with javascript minification and gave multiple ways of doing the same thing. More power to them. It doesn’t make Angular worse.

Debugging

I also would like to see errors thrown when a binding is broken. And finding the reason for an error in Angular is sometimes harder than it could be. There are tools out there to help, but the debugging story could definitely be improved.

Scope inheritance

Yep, this does inevitably bite new developers. But frankly you should be declaring your variables in each scope such that a child scope never even tries to inherit from its parent. This is definitely something that needs to be stressed, but once learned it’s not a problem. To me, a bigger issue is that statements like ng-if create a new inherited scope. I can’t tell you how many times that has bitten me (“why isn’t this @#$@# binding reflecting the variable’s new value? – Arghhh”). In hindsight, they could have done this differently, but again, once learned, you’re not even worrying about this and it’s not an impediment to writing code that works well.

Directives

Directives are hard. Granted. But they are worth learning. They are a key reason why Angular is so awesome! This is web development as it should be, with reusable components. Microsoft tried a long time ago, and that was awesome, too, even if it was browser specific. And web components in the next versions of the web will eliminate the need for directives. But for now, they’re the only way to create cross-platform reusable UI components, and they are worth learning. Plus, just like so many other technologies we use in various platforms, many times you’ll just be using an OS directive that does what you need and you’ll never have to know how the internals work.

Problems with people

With a well-written application, it’s pretty easy to look at controllers and services and see what they’re doing. And then you can look at the view and see how the properties in the scope are being used. I’m not sure what’s so hard about that. And as for the server developer understanding what’s going on with the front-end, well, that depends. If your server developers are coding in javascript, they’ll have no problem looking at the controller and service code on the client. If they’re not versed in javascript, or they don’t understand how two-way data binding works, they might have an issue. But I’m not sure how this is different than with any other framework.

Inability of server side rendering

This argument to me is ridiculous. Angular isn’t built to do server side rendering. If that is something you have to have, don’t use it. It’s an architectural choice. But the vast majority of apps written with Angular don’t need server side rendering. And as mentioned in the article, if you need to provide html-indexable versions of your pages for SEO, there are solutions that absolutely work.

AngularJS 2.0

There will be changes. I’m excited that they are looking to learn from the experience with 1.x and improve it in every way. How is this different from most other technologies. I guess we shouldn’t use Bootstrap since they changed things between 2.x and 3.x. Entity framework is out because v7 is re-architected. Wow, no MVC for me because they introduced Razor. For that matter, drop Webforms because MVC was introduced.

It’s a fact of life that technologies at some point get re-architected with breaking changes because 1) new tech becomes available (ES6, for example), 2) experience with the old version has shown room for improvement, and 3) better patterns are invented that make a developer’s life better.

The 1.x version of Angular will continue to be developed.  It will be a while before 2.0 hits mainstream usage.  Don’t *not* use Angular because a new version with breaking changes will at some point arrive.  Frameworks must evolve like this or they will die.  This is true of Angular or any other framework you might choose today.  Compare Angular 1.x to the other frameworks available today and decide if it serves your needs better (for you) than the others.  If it does, run with it and enjoy whatever benefits it gives you.  Oh, and of course all of this is open source, so your company will never be abandoned or your app obsoleted as long as you can write and change javascript yourself!

Summary

If you don’t like the opinions Angular introduces to application development, by all means, don’t use it. But it’s disingenuous to take your opinions and suggest that all opinions that don’t align with your personal development worldview must be wrong. To suggest that everything about an architecture that has room for improvements is therefore ill-conceived is just narrow-minded. Angular has many areas that can be improved. But for me, I chose Angular over webforms, mvc, jquery, knockout, etc., because, after working with alternatives, Angular was the framework that was best suited to the development projects with with I have been and am involved. If someone works with ember, react, etc., and decides that those are the best frameworks for the project they have at hand, then by all means use those.

The beauty of development, and hopefully part of the reason we as developers are passionate about what we do, is that we have choices. Things are constantly changing and improving. Nothing is perfect, but there are many solutions that are good enough, and most are much better than what came before. Find the framework that works for you, your team and your business owner and run with it. We should all worry more about delivering a solution that works for the business that needs it than worry about the framework we use to deliver the needed solution.

Yet another Angular focus directive

I’ve seen lots of Angular directives that set focus of an element based on its html name or id.  And I’ve seen a few other methods as well.  But I couldn’t find one that could handle these requirements:

  1. Keep trying to focus the element for a period of time (useful when there’s a delay in the element actually being displayed in the dom)
  2. If you put the attribute on multiple input elements, the first one would get the initial focus (useful if you have the first one conditionally displaying, and want to fall back to a second one if it isn’t)
  3. Allows you to conditionally have the next input field displayed on the page get the focus (useful if clicking a button on your page, for example, adds an input field you want focused)

So, I wrote the one you see below called, originally enough, anotherFocus. 

It should be added to an element with the attribute…

another-focus="domFocus"            

where, on your controller,

$scope.domFocus = { setFocus: true }

Then, after page is loaded and maybe you've focused an element, you can set $scope.domFocus.setFocus = true right before causing another input to be added with the directive on it.  The next element added with the directive would get the focus.

The directive as written will retry the focus call every 100ms for up to 2 seconds, but of course, you can always change that in the code.  If your page takes a while to load (mine sometimes takes half a second because of some processing it’s doing), this is crucial.

Hope this helps someone.

angular.module('app').directive('anotherFocus',
function ($timeout) {
    return {
        scope: {
            //should be set up like another-focus="domFocus"
            //where, on controller, $scope.domFocus = { setFocus: true }
            //then, after page is loaded an maybe you've focused an element, 
            //you can set $scope.domFocus.setFocus = true right before causing another
            //input to be added with the directive on it
            trigger: '=anotherFocus'
        },

        link: function (scope, element) {
            var attempts = 0;

            function timeout(ele) {
                ele.focus();

                //we're willing to try 20 times at 100ms for a total of 2 seconds
                //to wait for the element to be on the page and active
                if (ele != document.activeElement && attempts++ < 20)
                    $timeout(function () {
                        timeout(ele);
                    }, 100);
                //console.log('attempt' + attempts);
            }

            //start the initial attempt to focus this element
            scope.$watch('trigger', function (value) {
                if (value.setFocus) {
                    //stop future elements with directive from getting focus unless we turn on setFocus from controller again
                    value.setFocus = false;
                    timeout(element[0]);
                }
            });
        },

    };
}
);

Angular, Select Inputs and 0 Values With a Required Attribute

Have you ever had a situation where you were binding your select input to a set of objects like this:

[{ value: 0, key: ‘please choose’}, { value: 1, key: ‘texas’}, {value: 2, key: ‘georgia’}]

I ran into a situation where a service that was giving me the options for the select input was setting the value for the ‘Please choose’ option to 0 instead of to blank.  This meant that if this select input was required via a “required” or “ng-required” attribute, the “please choose” would cause the browser and angular to consider the field as having a valid selection.

I had two options: change the data itself so that it was set to null or blank instead of 0, or… I thought I might create a directive to handle this.  So I created the directive.  As you can see below, this is a simple directive I threw together to consider the select to be invalid if it’s required and the value of the option selected is 0.  Not complicated, but so far it’s worked great.  The nice thing is that it’s not meant to replace the required attribute, so you can leave it or the ng-required directive, and if you’re using the ng-required directive, setting it to an expression still works fine. 

Enjoy.

/* 
Directive: required-zero-doesnt-count
JW - 2014-11-16

There are some instances where a select input has an option with a value of 0, where 0 is considered to be a placeholder option.  In other words, if the select is required, 0 doesn't count as fulfilling the 
required validation.  However, just putting the "required" attribute on the select doesn't work, because while we know the business doesn't consider "0" a valid selection, the browser thinks it is.
This directive sets required validation to false if the 0 option is selected.  

Note that this is not in place of the required attribute, but is used alongside.  The required or ng-required is still needed, or else this directive will not check for a 0 selection.
*/

(function () {
    'use strict';

    var app = angular.module('app');

    app.directive('requiredZeroDoesntCount', [function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ngModel) {
                scope.$watch(function () {
                    //just returning a string that will be different if either view value has changed or required attribute has changed
                     return ngModel.$viewValue + "___" + attrs.required;
                }, function () {
                    if (attrs.required)
                        ngModel.$setValidity('required', ngModel.$viewValue && ngModel.$viewValue != "0");
                    else {
                        ngModel.$setValidity('required', true);
                    }
                });
            }
        };
    }]);
})();

Angular Gotcha – Watch out for Intra-Digest Changes!

The other day I had an issue with Angular that I hadn’t expected.  The deal was that I had the following scenario:

  • Changed the value of a scope variable.
  • Had a watch based on that scope variable changing.  The watch would trigger a DOM change.
  • Changed the value of the variable back to what it was.

Straightforward.  I expected the DOM to be changed.  But it didn’t.  What I forgot was that if the change from one value back again happened during the same digest cycle, it could be like it never happened as far as any watch expressions were concerned.

The idea of the digest cycle is something you have to understand deeply to really be good at Angular.  However, a scenario like this doesn’t happen enough for it to be something you watch for proactively, as opposed to reacting when the bug pops up.  But now, when writing Angular controllers and directives, I’m seeing places more and more in which I need to be aware of the implications. 

What I’d like to see in Angular is a way to force evaluation of watches from within a controller method.  As it stands now, you can’t force the apply/digest, because when in a controller method, you’re in the middle of one.  Having a method like $forceWatchEval() would be wonderful.  Easy for me to say… I’m sure there are complications in the Angular lifecycle that would probably make that harder than it seems.  And while I’ve explored some of the Angular source already, I don’t have time to dig this deeply, and even if I did, Angular v2 is going to change things drastically anyway.

Machu Picchu

I just got back from trekking the Inca Trail for four days, culminating in a visit to the cloud city of Machu Picchu.  Words don’t describe how amazing the trip was!  The hike was challenging, with too many steps uphill to count!  But as I’m here at my computer right now, I’m wishing I was on that trail again right this second, even the hardest, most grueling part.  If you’re a technologist, I challenge you to get out and get away… do something crazy!  You won’t regret.  I’m back, and more clear-headed, rejuvenated and excited about what I do than before I left.  Even if my preference would be to be standing at Sun Gate overlooking a lost city :).

IMG_9528_dxo

Using bearer tokens with SignalR

I am using bearer tokens to authenticate my Angular app with my backend WebApi, well, API.  I am adding SignalR to the app, and could not get user.identity.name to resolve to the currently authenticated user when trying to retrieve it from the hub OnConnected method.  Long and short, I had forgotten to add the bearer token to the SignalR ajax requests.  The code to do so is below.

var accessToken = localStorage.getItem("accessToken");
$.signalR.ajaxDefaults.headers = { Authorization: "Bearer " + accessToken };


Once that was done and my startup.cs file was correctly set to use bearer tokens, I was good to go.

Windows 8.1 Update (April 2nd MSDN release) Error Solved

Easy answer: Make sure you have enough disk space free before installing the update!

Long answer: So I immediately jumped at the Windows 8.1 Update MSDN download announced yesterday at Build.  Everything went great until it rebooted during the install.  It got to 77%, then hung for several minutes, then rebooted again.  I was then told it was reverting to the previous version of windows.  When I finally logged back into my machine, a nice app screen came up telling me that the update couldn’t be installed.  At the bottom was the following error code.  I tried this twice… same error at the same place both times.

0x101 0x20007

Sorry the screenshot below is so bad – my screen capture tools weren’t loaded when it was displayed, so I had to take a pic from my Surface I had next to me.

Anyway, I did some googling and found that there are logs here… C:\$WINDOWS.~BT\Sources\Panther.  I don’t remember now, but one of them had the activity log of the entire upgrade attempt.  At the bottom was the answer.  It referenced insufficient disk space!  I had 17gb left on my drive, so it never even crossed my mind that that could be the problem.  However, I cleaned up my HD and tried again with 47gb of space, and it worked perfectly!

image

 

 

 

 

 

Problem solved.

Six Technologies Poised to Change Our Lives

Virtual Reality Headsets

This could go badly.  VR Headsets from Oculus, Sony, and presumably others will provide a level of immersion in (games, work, etc.) like never before.  Sure, this has sort of been done before, but the products being built today are less prone to having users suffer from motion sickness, while the visual quality is much better and the motion sensing is top notch.  The problem is when this gets too good.  I know, movies have already been made about people preferring to live in their VR worlds rather than in the real world.  But look at how much time people spend in video games already, when the level of immersion consists of staring at a monitor.  Once you are so immersed you completely forget about the world outside your 3D, full-depth, motion-sensing, vibrating, visually incredible world, will people ever want to leave it?

3D Printers

3D printers… so much talk, so little practical use so far.  I have one, and it lets me do some pretty cool things to impress my friends and sate my electronics project enclosure needs, but outside of that, the average person has no reason to have one.  Yet.  But as everyone knows, it’s only a matter of time before the killer apps come.  What are they?  Well, if I knew, I’d make them and get rich.  But they will come.  And even without a single killer app, the ability to click Buy and print many objects we use every day will be incredibly valuable.  For that to happen, the printers will have to support multiple colors and dissolvable support materials at a consumer price. 

Meanwhile, there’s a bigger picture outside the consumer space.  Imagine whole buildings getting printed at once.  What will happen when an industrial 3D printer can be blimped onto a concrete foundation and, from there, print the whole house, conduits and all?  Or all other sorts of industries adopt them for consumer-directed pieces of their products?  Custom car… done.  Custom furniture… check.  On demand [insert product here]… check.

3D Vision

3D spatial mapping and vision by computers is going to be vital to manufacturing.  Why?  Because drones (see below) are going to be part of the building process for many products, and they need to know where to go.  Having 3d vision down to the millimeter will be crucial for directing these drones.  Mapping a plot of land will be done with 3D vision, not surveyors.  Oh, and then there’s video games.  Imagine being able to walk through your house, your friend’s houses, and your neighborhood with your tablet, then uploading the 3D map and textures to your favorite game.  Pair this with the VR headsets, and you’ll play whatever game of destruction you want where you live and work, without breaking anything.

3X Battery Improvement

We need better battery density, and we’ll get it.  Graphene, quantum physics, metamaterials.  Something, at some point, is going to increase battery life 3x in a cost effective manner.  When it does, say bye to gasoline cars.  That will be huge.  Cars will be simple to maintain (no engine) and cheaper to run.  Our dependence on foreign oil will be broken for good.  Phones will last a day with 3x the features (you don’t think phone makers would let you get three days when they can add more features, did you?).

Drones

Drones… where to begin.  First, privacy was already dead, and drones just make it even deader.  There will be no place a drone can’t sneak into with camera and microphone in tow.  Just check out the military’s development of super-small drones to see what I mean.  That’s the bad news.  The good news is that drones will be used for manufacturing in new ways.  If a house is going to be four-sided brick, easy.  Just have the drones lay it.  No more paying a huge premium for a quality, good looking house.

Quadrocopter cars

This is the one that’s not on most people’s radar, but should be.  Everyone thinks the future of transportation is autonomous cars, and maybe it is.  But why are cars so hard to make autonomous?  First, legacy.  We have legacy streets, cities, vehicles and laws that were never made for cars that drive themselves.  If we could redo everything and have wider streets, pedestrian crosswalks that were always elevated, and vehicles that were built from the start to communicate with each other, maybe, maybe we could make it work.  But cars run in a very narrow two dimensional space that can’t be enhanced.  If a tire blows or a pedestrian isn’t where they’re supposed to be, or there’s snow, or heavy rain, or an accident around the corner you can’t see, and a car makes a mistake, we won’t tolerate it. 

Now, with all that said, sure, given enough time, anything I say will be wrong.  But I think there’s time for a new mode of transportation to take the place of the car.  I think quadrocopters as human-moving vehicles could make a lot of sense.  First, the challenges.  First, there’s the power requirements.  This is the single biggest challenge, and without the battery improvements above, this idea will never work.  But let’s assume (big assumption, but doable) that we overcome the power needs.  The second challenge is safety.  You’re in the air and something goes wrong.  You can’t exactly coast to the curb.  That’s a problem.  However, people die on the roads on a consistent basis, so automobiles aren’t exactly a model of safety from an absolute perspective.  The great thing about quadrocopters (ok, so the actual vehicle might have three, five, six or however many rotors – but quadrocopter sounds good) is that an incredible amount of redundancy can be built into a quadrocopter.  First, the batteries can be separated into two packs that each feed two opposed rotors.  Second, each rotor can have individual motors and redundant electronics.  With software, it’s been shown that a quadrocopter could land itself with half of the rotors non-operable. 

So those are the big negatives.  The positives are much bigger than the negatives.  Where to begin?  First, as the crow flies distances.  No more right-angle commutes.  The shortest distance wins.  Second, capacity.  We would now be operating in a 3D space.  This means there’s no real limit to the number of “lanes” and no limit to how many of those lanes we can stack on top of each other.  Third, safety.  Wait, didn’t I list that as a negative.  Yes, for the people in the quadrocopter in the event of something catastrophic.  But for pedestrians, it’s a new world.  There are no pedestrians in the air.  Problem solved.  Fourth, autonomy.  Making a car be able to sense it’s environment is incredibly hard.  Making an object in the air sense its environment is much easier.  Landing would be the only challenge, and it’s not a huge challenge, since you’re working in a vertical environment instead of a horizontal environment.

Summary

Why’d I write this?  Because I had some extra time today, that’s why.  As you can tell, I’m a guy who reads too much about technology.  It was time to write down some of the future thoughts swirling in my brain.  It’ll be interesting to see what I got right and what I didn’t.  Personally, if I just get the quadrocopters right I’ll be a happy commuter!