Technology, Continued...

Ramblings about business, technology, development and my life

NAVIGATION - SEARCH

Eero vs velop vs orbi

The short answer is that Eero rocks.  So I bought Orbi a couple years ago from Costco, and could never get all of my devices, especially my wifi cameras, to work consistently.  I returned it and bought Velop.  Same deal, although it wasn't quite as bad.  Well, it was bad enough that I finally sold them on ebay and went Orbi again, because 1) the firmware had supposedly come a long way since my first purchase, and 2) they had an outdoor unit.  Well, this second try still had lots of issues with the cameras, and purple rings, and poor performance, etc..  SOOOO... I decided one night, before returning Orbi yet again to Costco, to go buy Eero and see what happens, because, hey, I had 15 days to return it to Best Buy.

Amazing!  The UI was hands down the best (live display of what eero you're connected to and much, much more).  The setup experience was the best (three eeros and two beacons).  And most important, it just worked!  My cameras all started showing their max fps consistently, and haven't missed a beat through firmware upgrades, kids unplugging them, etc..  I had one time where I put a beacon too close to an eero and it caused a bit of issue, but i just moved it and all was well.  Other than that, 0 issues.  0.  I even put a beacon on a ceiling outlet in my outdoor pavilion to get outdoor coverage.

It's been a month or two now, and I'm just totally blown away with how much better my life is because everything just works with Eero.  Needless to say, I returned my second purchased Orbi setup and haven't looked back.  Thanks, Eero!

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.