UIB (Bootstrap) Component Modals Made Easy

So UIB decided to support “component modals”. Unfortunately, the way I see it, the components need to be “dirtied” with the modal logic, meaning you will also need to include resolve and close in every component you want to display as a modal. Inside the components constructor or $onInit you then proceed to “resolve the resolve” (i.e. if(resolve){ this.myBinding = this.resolve.myBinding; ... }) which is quite annoying. Why isn’t it possible to JUST WRAP A COMPONENT IN A MODAL? So that’s what I set out to do: I created a wrapper-modal-component for my modal-components.

The idea behind was, to abstract away the modal logic from the component logic. Most of the component doesn’t need to know that it’s wrapped by a modal.

Untitled drawing (22)

Now in this sketch, the inner component functionality, doesn’t need to know ANYTHING about the modal. The only thing where it might be useful to be aware that it’s a component, is the UPDATE button, since you might want to close the modal after the update. But you can easily and beautifully do this by emitting an event.

But first things first. So I thought what’s the minimal information that a component-modal-opener requires? I.e. openModal, what does it need to know?

  1. It needs to know the name of the modal
  2. It needs to know the bindings, in case there are any

So an implementation of `openModal` could look something like this:

public openComponentModal (componentName: string, bindings?) {

  let resolve = {
    component: () => {
      return componentName;
    },
    bindings: () => {
      return bindings;
    }
  };

  return this.$uibModal.open({
    animation: true,
    component: 'modal',
    resolve: resolve
  });

}

Okay, so what happened here? Lets say this is in my Utils service, so from now on, I can always open modals just with e.g.

this.Utils.openComponentModal('my-component', {
  bindingOne: this.bindingOne,
  bindingTwo: this.bindingTwo
  ...
});

Handy, isn’t it? The modals will look consistent across your app, and the component isn’t spoiled with modal logic. But how is this achieved?

Notice how I DON’T open my-component directly, but instead I open the component modal. The component modal is where the magic happens and it looks like this:

Controller:

@Component('myApp', 'modal', {
  templateUrl: '/components/directives/modal/modal-component.html',
  bindings: {
    resolve: "<",
    close: "&"
  }
})
class ModalComponent {

  public resolve;
  public close;

  static $inject: string[] = ['Utils', '$compile', '$scope', '$log'];

  constructor(
    private Utils: Utils,
    private $compile,
    private $scope,
    private $log: ILogService
  ) {}

  public style;

  $onInit() {

    this.initModal();
    this.initCloseButton();

    this.$scope.$on(EmitEvents.MODAL_CLOSE, () => {
      this.close();
    });

  }

  private initModal() {
    if (this.resolve && this.resolve.component) {
      let bindingsString = (bindings): string => {
        let str = "";
        if (bindings) {
          for (var property in bindings) {
            if (bindings.hasOwnProperty(property)) {
              str += " " + this.Utils.camelCaseToDash(property) + "=\"$ctrl." + property + "\"";
              this[property] = bindings[property];
            }
          }
        }
        return str;
      };

      let completeString = `<${this.resolve.component}` + bindingsString(this.resolve.bindings) +`><${this.resolve.component}>`;
      let compiledHtml = this.$compile(completeString)(this.$scope);
      $('#tb-modal').html(compiledHtml);
    } else {
      this.$log.error("Modal not correctly initialized");
    }
  };

  private initCloseButton() {

    this.style = {
      position: 'absolute',
      top: '-20px',
      right: '8px',
      'font-size': 35 + 'px',
      'z-index': 1000,
      color: this.Utils.primaryColor
    };

  }

  public open

}

View:

<div class='modal-wrapper'>
  
  <div style="position: relative">
    <button ng-click="$ctrl.close()" ng-style="$ctrl.style">
      <span style="position: relative">
        <i class="fa fa-circle" aria-hidden="true" style="position: absolute; color: {{$ctrl.color}}"></i>
        <i class="fa fa-times" aria-hidden="true" style="position: absolute; color: white; font-size: 20px; top: 7px; left: 7px;"></i>
      </span>
    </button>
  </div>
  
  
  <div id="tb-modal"></div>
  
</div>

Uff, pretty crazy. But the beauty about it is, that the crazyness is abstracted away in an isolated component. All the other things left and right of it are left untouched. So the crazyness quickly explained:

  1. The view has simply a close button and a div which is replaced with the actual component by jquery
  2. The controller takes a resolve from uib.resolve, resolves it, and compiles the component.
  3. The controller binds to an emit event.

Now, if e.g. the UPDATE button in the component should close the modal, you simply make it run:

this.$scope.$emit(EmitEvents.MODAL_CLOSE);

Meaning the component is still coupled to a modal, but much more lightly than before.

I hope this gets you started with your modal-wrapper-component. 🙂

Time Capsule / Time Machine through Raspberry Pi

I’ve followed multiple tutorials on how to setup time capsule through raspberry pi. There’s one that’s by far the simplest & it works: https://www.raspberrypi.org/forums/viewtopic.php?f=36&t=47029

In fact, the others are so much more complicated that I thought this wouldn’t work and tried it last: What a mistake.

Here’s a short re-write with a few minor changes, also covering the formatting of the storage drive.

Format the Storage Drive

On the PI:

Run lsblk -o KNAME,TYPE,SIZE,MODEL in order to find your drive. Then run:

mkfs.ext4 /dev/sda

Replace sda with the corresponding drive.

In case you want a partitioned drive: Tutorial: http://askubuntu.com/questions/517354/terminal-method-of-formatting-storage-drive

Getting the required Packages

The communication between Mac and PI will go through netatalk:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install netatalk

Setting up

Find the device number using lsblk -o KNAME,TYPE,SIZE,MODEL as above, then:

sudo mkdir /mnt/TimeMachine
sudo echo "/dev/sda<device number> /mnt/TimeMachine auto defaults 0 2" >> /etc/fstab
sudo mount /dev/sda<device number>
sudo chmod 777 /mnt/TimeMachine

then

sudo echo "/mnt/TimeMachine \"Time Machine\" options:tm" >> /etc/netatalk/AppleVolumes.default
sudo service netatalk restart

Now restart the pi.

Select the Disk on the Mac

Now you’ll automatically discover the new Disk in the Time Machine Preferences.

Note: If you get an error like

The backup disk image “/Volumes/backups-1/<your computer name>.sparsebundle” could not be created

it’s probably because you plugged out the drive from the running pi and then plugged it back in. Just restart the pi and it should work again. It also might be necessary to run the following command in the terminal first:

defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1

– the end –

Yet Another Install Guide For Raspberry Pi 3

 

I found the installation & setup of the raspberry pi to have quite a few pitfalls, so here’s my own guide for a headless Pi installed through a MAC.

Step 1: Format your SD Card properly!

Use the Disk Utility to format the drive (MS-DOS, Masterboot Record).

screen-shot-2017-01-05-at-00-26-55

When you then type diskutil list into your terminal, the SD Card should be formatted like so:

screen-shot-2017-01-02-at-01-45-39

It’s important that the type is DOS_FAT_32. Otherwise you might run into error messages like Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2) later on. If it’s not yet formatted like this, you can try the following app (SDFormatter) https://www.sdcard.org/downloads/formatter_4/

Step 2: Download the OS

On https://www.raspberrypi.org/downloads/ you find the images available. I strongly recommend to use the Raspbian Lite image (for headless use of the PI!), unless you know what you’re doing. For example, if you install Ubuntu Snappy, you’ll have no chance to follow any tutorial later on, as they all rely on apt-get install, which is not available on “Snappy”.

Step 3: Install the image

diskutil unmountDisk /dev/disk<NUMBER>
sudo dd if=<myfilename.img> of=/dev/disk<NUMBER> bs=1m

where <NUMBER> refers to the disk number of the SD Card you see when you run diskutil list. The installation takes a long time (~1h). It doesn’t display any verbose output, so you’ll just have to be patient. Once finished a success message is displayed:

screen-shot-2017-01-02-at-09-31-45

Step 4: Power UP & Enable SSH

Insert the micro SD Card into your PI, then connect the following things:

  1. Ethernet / LAN cable
  2. Monitor (only during setup)
  3. Keyboard (only during setup)
  4. Power

It seems to be possible, yet troublesome, to enable ssh without a monitor / keyboard, so here’s the way with keyboard + monitor. Once started up, login to the Pi using user pi and password raspberry. Then type sudo raspi-config and go to “Interfacing Options”. There, enable SSH and reboot the PI.

Step 5: Login via SSH

First, you’ll have to find your PI on your network. If you connected a monitor, you’ll see the IP of the PI in the boot log. If not, you can find it’s IP by typing arp -a and checking which devices might be the pi.

Then login using ssh pi@<Pi’s IP>

The password is raspberry.

Step 6: Passwordless Access to the PI

On the PI:

cd ~
install -d -m 700 ~/.ssh

On your mac:

cat ~/.ssh/id_rsa.pub | ssh pi@192.168.192.64 'cat >> .ssh/authorized_keys'

(replace the IP by the IP of your PI).

Wait for the Bindings of a Directive in Angular

If you’ve worked with angular for a while, you’ve probably found yourself having a directive like

<my-directive my-prop="myProp"></my-directive>

where not having myProp ready yet (e.g. it’s retrieved from the server asynchronously) lead to problems. For example if the first thing you do in your directive is to call myProp.sayHello(), your app will crash saying cannot read property sayHello of undefined. Or maybe the displayed directive just will look wrong without myProp.

So you recalled yourself “ah well, ng-if prevents things from rendering, so I’ll just put an ng-if there”. So your code looked like that

<my-directive my-prop="myProp" ng-if="myProp"></my-directive>

Every once in a while myProp is not an object, but a number or a boolean instead, which breaks the desired behaviour so you’ll have to fix the bug by something like

<my-directive my-prop="myProp" ng-if="myProp !== undefined"></my-directive>

Phew, problem dodged. But then the next time you use your directive in another place, you’ll forget to put the ng-if there again! You’ll have to remember the ng-if each time you use your directive. How do you communicate to another user (e.g. team member) of your directive, that the ng-if is required? Do you write this

{
  myProp: "=" //this is very important property, so put ng-if=myProp on the directive when you use it
}

in the source of the directive? As you can see, this is not ideal.

So what can you do to alleviate the pain? I think it would be best if there were a flag by angular, something like

{
 myProp: "=r"
}

(where r stands for required). Of course it’s a bit confusing since there is also the flag "=?" which means that you can actually leave away the binding (i.e. <my-directive><my-directive> is allowed). I guess what angular intended to do is saying “you specified "=" and not "=?" so anyone using the directive will know it’s a required property. So if anyone passes in undefined because a property is received asynchronously it’s their fault.”. The problem with this line of thinking is that it can cause a lot of bugs. Let’s say several directives make use of myProp which is loaded synchronously in the view-controller. But then for one reason or another you’ll make myProp asynchronous. First of all you probably won’t remember that you need to put ng-if’s everywhere. Second, you probably don’t know what’s all depending on myProp. And third and worst, your app might run fine locally because the local server responds fast enough, but then crash in production!

So since Angular doesn’t provide you with a flag for actually waiting for bindings (until they’re not undefined anymore), is there another way than the ng-if? The only thing I could come up with so far is wrapping your directive in another directive to abstract away the necessity of the ng-if for users of the directive. This could go like so:

<my-directive-implementation ng-if="myProp"
                             my-prop="myProp">
</my-directive-implementation>

where the controller has to bind the property

// controller of my-directive
...
{
  myProp: "="
}

Then, in my-directive-implementation, you can put the code you originally intended for my-directive. Another possibility would be to just put the ng-if on the top level node of your directive

<div ng-if="myProp">
  ...directive stuff
</div>

and in the the directive-controller watch the property and only do stuff once the property is not undefined anymore:

scope.$watch('myProp', function(newValue, oldValue){
   ...initialize the controller
}

Of course this is quite a lot of noise for something that could have just been achieved with a flag provided by angular. I mean, as mentioned it’s reasonable to let the invoker make sure that a property is non-null, but since it’s quite a common use-case to retrieve myProp asynchronously, I think it would have been nice if they provided a way to only render directives once props are not undefined anymore. If you have other solutions or inputs for this, please let me know in the comments!

Angular 1 (ng1) vs Angular 2 (ng2) Two-Way Data-Binding for (nested) Components in 2017

Update: An article focusing more strongly on Angular 2 can be found here https://www.bersling.com/2017/05/24/communication-between-components-in-angular-2/. It also elaborates the observables concept in more detail.


Two-Way Data-Binding has long been one of the unique selling points of Angular 1 (ng1 in the following), until people started to complain that it slows down the apps too much. This was one of the core reasons, why the Angular Team opted to create Angular 2 (ng2 in the following): to make Angular faster by “removing” two-way data binding. But did they really remove it? And what’s the suggested way of data binding then? That’s the topic which we’ll tackle here.

Let’s start with a common misconception:

In ng2, the parent holds the data and the child can’t modify it.

That’s not entirely correct. Correct would be:

In ng2, property bindings (the ones with square braces [] ) are PASSED BY REFERENCE. Therefore the data / view is updated app-wide, when a field of a bound object is changed.

Let me prove this to you in the following ng2 app:

This was achieved by simply using

[(ngModel)]="item.name"

on the innermost element. So wait, didn’t I read like 1 Million times that when I pass down an object with [] that the child can’t modify it? Well yes, but that’s a lie. The child can modify it because it’s passed by reference, unless it’s a string or a number or another primitive that’s passed by value. Let’s capture the difference:

ng2 and ng1 data binding are only different in case of the entire bound object being replaced. This is always true for strings, numbers, booleans and other primitives.

In the example above, this would mean if I clear or reassign (e.g. item = {} ) on any nested child, I break the link of the updates in ng2 but NOT in ng1. ng1 will look through all components, searching for item in order to update it.

Okay, so this begs some questions.

  • Is modifying the data in a child-component encouraged?
  • What kinds of problems could arise leveraging the reference-binding?
  • What should I do when I need the parent to do something on the change of the data?
  • What should I do if I don’t have an object, but instead primitives, or I want to swap the entire object?

A lot of questions. Let’s first do a quick recap of the “old way” of doing two way data binding in ng1, and then looking at the new, recommended way(s).

Angular 1 two-way data-binding in components

Here’s a quick reminder how two-way binding in ng1 worked. Let’s say we have a wrapper component, holding two child components: one to edit the data and one to display the data of the wrapper.

<my-prop-wrapper my-prop="myProp">
  
  <edit-my-prop my-prop="myProp"></edit-my-prop>
  <display-my-prop my-prop="myProp"></display-my-prop>
  
</my-prop-wrapper>

The display got immediately updated when you bound my-prop to the directive like so:

scope: {
  myProp: '='
}

But this won’t work in ng2, since communication only happens from parent to child in property binding. The edit-my-prop directive doesn’t propagate changes upwards to the parent and then from the parent back to the display anymore. You’ll have to do that yourself. So how can you do it?

“Official” ng2 way to update data across components

In order to get the information from the edit to the display, you’ll  somehow need to get the wrapper to listen to events in the edit. In ng2 a [] bracket signifies a flow of information from parent to child and a () bracket signifies a flow from child to parent. So your template would need to look like so:

<my-object-wrapper my-object="myObject">
  
  <edit-my-object [myObject]="myObject" (myObjectChanged)="doOnChange($event)">
  </edit-my-object>
  <display-my-object [myObject]="myObject"></display-my-object>
  
</my-object-wrapper>

The display only needs to receive information (i.e. []), but the edit needs to receive and emit information. Now inside of the edit-compontent.ts (or whatever name it may have), the emission of information must be triggered. How? With ng2’s EventEmitter and Output classes. Import those into your file, then:

@Output() myObjectChanged = new EventEmitter();

You can then trigger an event by myObjectChanged.emit({value:this.myObject}).

This will trigger the doOnChange Function in the parent, which could for example do the following:

doOnChange(evt){
  this.myObject = evt;
}

HOWEVER, notice that it doesn’t have to be done like this. You could just as well utilise the Observable Pattern with RxJS. That’s actually what I’d recommend you to do, we’ll discuss it in a moment.

How you could do it in ng1, like you would do it in ng2

In ng1 we can bind properties with =, with @ and with & . I personally never really used & since there’s already too many concepts, but with this you can simulate the ng2 behaviour.

For example you can have in your parent template

bla bla <inner do-on-event=myFn($event, someData)></inner>

and then bind it to the child (called inner here) like so (in typescript):

<button ng-click="omgImClicked($event, 'cool stuff')">Click me</button>
bindings: {
  doOnEvent: "&"
}
...
public omgImClicked(e, data) {
  doOnEvent({
    $event: e,
    someData: data
  });
}

In case you were like “wtf” here a lot, maybe read this article: http://www.codelord.net/2016/05/13/understanding-angulars-and-binding/

However, note that this can become cumbersome quickly, as components become nested!

Deeply Nested Components

As you write a complex app and reuse more and more components, the components get smaller and and more nested as part of a process. So it’s important to understand how nested components will work.

Function Binding in ng1 (not recommended)

In ng1, if you want to go with the function binding approach, you’ll have to do something like the following. Let’s say we have a somewhat complex update function in our “data owner”:

public updateTask(updateInformation: {
  task: Task,
  field?: TaskProperty,
  listindex?: number
}) {

  let errorFn = (errorResp) => {
    this.Notify.errorResponse(errorResp);
  };

  let successFn = (resp) => {
    this.task = angular.copy(resp.data.task);
  };

  if (!updateInformation.field) {
    this.TaskService.update(updateInformation.task).then(successFn, errorFn);
  } else if (!updateInformation.listindex) {
    this.TaskService.updateProperty(updateInformation.task[updateInformation.field], updateInformation.task, updateInformation.field).then(successFn, errorFn);
  } else {
    this.TaskService.updateListItem(updateInformation.listindex, updateInformation.task[updateInformation.field][updateInformation.listindex], updateInformation.task, updateInformation.field).then(successFn, errorFn);
  }

}

I’ve already aligned this for proper usage for passing down with &, since if you would use multiple arguments instead of a json, you’re gonna have a bad time. Well actually, if you use this method you’re gonna have a bad time anyways.

youre-going-to-have-a-bad-time

This is because you’ll have to define a new function in every nested component, if you use multiple arguments. You’ll see what I mean if you try it out, but I’ll spare you this here.

Next, in the template we can call it like this:

<child update-task="$ctrl.updateTask({task: task, field: field, listindex: listindex})">
</child>

and then in the grandchild we could also use

<grandchild update-task="$ctrl.updateTask({task: task, field: field, listindex: listindex})">
</grandchild>

(exactly the same!). Let’s say the event happens in the grandchild, so we could use something like:

public updateTitle() {
  this.updateTask({
    task: this.task,
    field: 'title'
  });
}

Well, that’s it.

Anyways, I have a few problems with this passing down of an “updating function”, which now seems to be the recommended way:

  • It’s a second “update-object/function”, alongside the main object task that needs passing down. What used to be magic and nice with two-way binding, assuring my “task” was the same everywhere now requires a second object/function being passed around.
  • It’s a lot of duplicated entries (“field: field” etc), but that’s necessary for multiple arguments.
  • Those entries are in the html, how ugly is that?
  • When someone else reads my code, how is this person supposed to know what updateTask does?!?! Before it was kind of clear because I just used a service and the databinding took care of itself, but now I have to go 10 directives/components up to find the “owner of the data” and check what this owner intends to do with the data.

Using $emit (not recommended)

With emit, you’d let the child (or grandchild or whatever) “bubble up” and event. For example the innermost child can tell it’s parent “Hey I had an event, I made poopoo”. Then the parent can tell the grandparent and so forth, until the one responsible for cleaning up the poopoo will take care of the mess. This is also not really the best choice, since it’s semi-global events flying around. You’ll emit a string like OBJECT_CHANGED which then can be viewed by all parents up to the rootScope. When you accidentally give the same name to multiple events you’re going to have a bad time.

Using $broadcast (not recommended)

Instead of bubbling up with $emit, you could also broadcast an event from the rootScope. That’s also bad, since all the components with a listener $scope.on('BROADCASTED_EVENT') will react to this, so it’s global and, well, you’re going to have a bad time…

Using Observables with RxJS (RECOMMENDED)

The observable pattern is mighty, flexible and the way forward in many systems. Meteor, ng2 and ReactJS all adopt the concept, just to name a few. But observables aren’t just something you can have only in some frameworks, it’s basically just a programming pattern. And it’s quite simple, you just subscribe to events that are published. There is the framework agnostic library RxJS (Reactive Extensions for Javascript) that’s maintained by Microsoft and used by almost everyone dealing with observables in the Javascript World.

There’s plenty of pages explaining the nitty gritty of it, so here’s just the broader overview:

    1. You hold the data in a service. To do so, a kind of unique id/key is required to store the data in a map (key value pairs). Database entries are especially well suited for this, since they usually come with an id anyways.
    2. The service has a changeMyData method.
    3. The parent is subscribed to an observable in that service.
    4. When the service changes it’s data, the parent is notified, adapts its own data, and the changes are propagated to all children.

Here’s a quick example how you would go about data binding with RxJS.

In this example, a central item-service holds the data. It is always immediately clear who the “owner of the data” is (the service). It is also always clear where to apply the update, it’s also the service. What’s even nicer, the binding syntax becomes completely unnecessary. Notice how both <detail> and <remove-item> components don’t take any input properties, yet the object updates:

 <b>Angular 2 Component Using Observables!</b>
 
 <div style="border: 1px solid blue; padding: 5px; margin-bottom: 2px">
 <detail></detail>
 </div>
 
 <div style="border: 1px solid red; padding: 5px">
 <remove-item></remove-item>
 </div>

This is because <detail> listens to changes in the items stored in the item-service. That’s the simplest, cleanest and fastest approach if you ask me.

Of course this is only useful if we’re actually talking about data. If you have simple UI components that are like <my-circle color="red" size="15"></my-circle> it’s still simpler to just use property binding. But in the case of actual “data-objects”, like my-item it’s better use the approach with the service. As a rule of thumb, you could use:

If your object has an id, use the Observable + Service pattern.

Conclusion

As always in the fronend world, it’s a bit of a mess. Many concepts, many possibilities to achieve the same results, what’s the best choice? Some people would say “it depends”, but sometimes we say “it depends” too much because devs can only get really familiar with a certain number of concepts and some things are just plain stupid. The Front-End world is slowly consolidating towards observables for handling events.  And so should you.

WINNER: Observables with RxJS

6407041

Bootstrapping an Angular 1.5 Component with Typescript

Angular 1.5 introduces the “Component” concept in order to get closer to Angular 2. By now you might have started to use typescript in your project, but upgrading to Angular 2 was too big of a step. However, you can start writing “Components” in an exact-angular2-style. Here’s what you’ve got to do.

First of all you’re going to need the following code to make annotations work:

//component.ts
function Component(moduleOrName: string | ng.IModule, selector: string, options: {
  controllerAs?: string,
  template?: string,
  templateUrl?: string,
  bindings?: any
}) {
  return (controller: Function) => {
    var module = typeof moduleOrName === "string"
        ? angular.module(moduleOrName)
        : moduleOrName;
    module.component(selector, angular.extend(options, { controller: controller }));
  }
}

This will allow you to use annotations to define components.

A ready-to-use component can then be generated with the following scripts:

#creates skeletton
#argument: name in any case e.g. bla-bla or blaBla or BlaBla

pascalcase="$(node changecase.js ${1} pascalCase)"
paramcase="$(node changecase.js ${1} paramCase)"
camelcase="$(node changecase.js ${1} camelCase)"

mkdir WebContent/components/directives/${paramcase}

echo "
@Component('taskbaseApp', '${camelcase}', {
  templateUrl: '/components/directives/${paramcase}/${paramcase}-directive.html',
  bindings: {
    somebinding: \"<\" // One Way Binding
  }
})
class ${pascalcase} {

  public somebinding: string;
  static \$inject: string[] = ['Utils'];

  constructor(private Utils) {}

  public sayHello() {
    console.log('hi')
  }

}
" >> WebContent/components/directives/${paramcase}/${paramcase}-directive.ts


echo "<div class='${paramcase}-wrapper'>

  <button class=\"btn btn-default\" ng-click=\"\$ctrl.sayHello()\">Hello {{\$ctrl.somebinding}}</button>

</div>" >> WebContent/components/directives/${paramcase}/${paramcase}-directive.html


# Compile
cd WebContent/components && tsc

echo "Usage:

<${paramcase} somebinding=\"'World'\" ></${paramcase}>

"

and

//changecase.js
var changeCase = require('change-case');

var caseType = process.argv[3];
var inpt = process.argv[2];
console.log(changeCase[caseType](inpt));

Note: You need to `npm install changecase –save` in order for the scripts to run first.

That’s all.

Migrating an Angular 1 app to Typescript with Modules

Migrating an Angular App to Typescript with optional ES6 Modules

I know, I know, Angular is pretty outdated, but some of us have apps in production running on Angular and would like to introduce typescript anyways… This being said, working with an Angular 1 app with typescript you’re in a really weird place right now. Half of the time when googling “angular typescript” stuff, you’ll find angular 2 answers, and in order to get angular 1 closer to angular 2, the angular team introduced even more concepts to the already overloaded angular 1… But that’s just how it is.

Assuming ui-router is your routing solution, here are the steps for migrating an existing angular app to typescript.

The Easy Way: Without Modules

1) Rename all your js files to ts files

That’s an easy one, just rename all the files. If you have many files, you could use something like the following python script:

import os

for path, subdirs, files in os.walk("./"):
 for name in files:
 oldPath = os.path.join(path, name)
 newPath = oldPath.replace(".js", ".ts")
 os.rename(oldPath,newPath)

2) Install Typings

Angular 1 is written in js not in ts. So in order to get code completion from your IDE and tell typescript the “angular” object exists, you need to get the type definitions. You could skip this step, but it’s not a lot of effort and prevents wiggly lines in your editor and errors from the ts compiler (but it would transpile anyway).  To do so, install “typings” and then run typings install with the following typings.json file:

{
  "globalDependencies": {
    "angular": "registry:dt/angular#1.5.0+20160819155010",
    "angular-ui-router": "registry:dt/angular-ui-router#1.1.5+20160810191828",
    "jquery": "registry:dt/jquery#1.10.0+20160704162008"
  }
}

If you don’t want modules, that’s kind of all there is to it.

3) Compile your code

Put this tsconfig.json at the root of your project

{
  "compilerOptions": {
    "target": "es5"
  }
}

and then run tsc in the command line (also from the root of your project). This assumes you have the typescript compiler installed.

The Hard Way: With Modules

If you don’t know the basics of ES6 modules, maybe it’s a good idea to read this article on typescript with ES6 modules first.

In order to get things running with modules, a little more work is required. Here is a complete working example, that will be discussed in the following.

To use modules, you’ll need a module loader, here we’ll use SystemJS. You can start setting up everying like without modules, except that your tsconfig should now be:

{
  "compilerOptions": {
    "module": "system",
    "target": "es5"
  }
}

4) Loading the Main FIle With SystemJs

For using modules, you want to have one main module that you import using SystemJs. But if you just import your “app.js” with SystemJs (like so System.import('app.js')), then it will break your app. The reason for this is that ng-app="myApp" (or however you called your app) will be loaded before app.js is loaded. So here’s the first step. One possible solution for this is to bootstrap manually, so your index.html would read:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Typescript Modules</title>
    
    <!-- get angular -->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.3.1/angular-ui-router.min.js"></script>
    
    <!-- get systemJS from somewhere -->
    <script src="https://code.angularjs.org/tools/system.js"></script>
    
    <script>
      System.config({
        baseURL: './',
        defaultJSExtensions: true
      })
    </script>
    <script>
      System.import('app.js').then(function() {
        angular.bootstrap(document, ['myApp']);
      });

    </script>


  </head>
  <body>


    <div ui-view></div>
    <!-- We'll also add some navigation: -->
    <a ui-sref="state1">State 1</a>
    <a ui-sref="state2">State 2</a>

  
  </body>
</html>

Note how there is no ng-app attribute in this code anymore!

(Another other possibility is to also load Angular with SystemJS, but this is not discussed here)

5) Rewriting Your Controllers, Services, Directives and Components to Module Syntax

Since Angular 1.5  Components are the suggested way to do things, but let’s say you still have some 1.4 code and you’re using controllers… Then those controllers would have to be rewritten like so:

export class HelloWorld {

  static $inject = ["$scope"];

  constructor (private $scope) {
    $scope.name = "World"
  }

}

This is “not recommended” as you should use “controllerAs” syntax or components, but if you’ve got a lot of code, you’ll be just glad there is a way of doing it without “controllerAs” syntax

6) Importing

Now comes the fun part, you can import your controllers. This would be the app.ts :

import {HelloWorld} from "./hello-world";
import {GoodbyeWorld} from "./goodbye-world";

var myApp = angular.module('myApp', ['ui.router']);


myApp.config(function($stateProvider, $urlRouterProvider) {
  //
  // For any unmatched url, redirect to /state1
  $urlRouterProvider.otherwise("/state1");
  //
  // Now set up the states
  $stateProvider
      .state('state1', {
        url: "/state1",
        templateUrl: "partials/state1.html",
        controller: HelloWorld
      })
      .state('state2', {
        url: "/state2",
        templateUrl: "partials/state2.html",
        controller: GoodbyeWorld
      });

That’s it. That’s how you’d use modules with systemJS and typescript. Again, here’s the complete code: Final Code.

ES6 Modules and Typescript

The whole thing is still pretty crazy as of August 2016. If you want to develop your frontend with typescript, you’ll probably encounter all of those “things”:

bower, npm, node, grunt, gulp, typescript, tsconfig, tsc, transpile, es6, javascript2015, module, module loader, import, export, require, systemjs, amd, umd, commonjs, babel, traceur, browserify, webpack…

Those are just some things mixed together in a wild manner, but the sheer amount of tools & concepts is nuts.

Okay, so what’s the whole point anyways? You want to use typescript and this usually goes hand in hand with the import / export syntax. Import / export is from “es6” = “javascript2015”, but this javascript version is not fully supported by most browsers yet. And you don’t want to build your production app in a language that won’t run in most browsers. So what can you do? You can use something that does the following:

MAP ES6 to ES5

Who can do this? Babel, typescript and traceur for example. Forget about babel and traceur and use typescript.

But if you use import / exports in your code (i.e. modules) the es5 generated by typescript will not run by itself. Here you have two choices:

  1. Don’t use modules.
  2. Use a module loader.

Unfortunately there is no way around using a module loader, if you want to use import / export in your code. If you already have a large app, you have to think this through, as introducing modules implies quite a lot of refactoring. The rest of this article assumes you decided to use modules. A possible and not all-too-stupid choice for a module loader is SystemJS.

So, in summary what happened until now:

  1. ES6 has “cool new features you want to use”, but browsers don’t support them yet. (But probably you were kinda dragged into this by starting with typescript)
  2. In order to use es6 syntax today to develop a production ready app, we thus somehow need to map es6 to es5. Typescript does this for us.
  3. The es5 generated by typescript doesn’t run by itself, in case you are using modules (i.e. there is import / export in your code). In order to load those modules, you’ll need a module loader like SystemJS.

Here’s a minimal “app” that is built around those concepts:

index.html

<!DOCTYPE html>
<html lang="en">
 <head>
 <meta charset="utf-8">
 <title>Typescript Modules</title>
 
 <!-- get systemJS from somewhere -->
 <script src="https://code.angularjs.org/tools/system.js"></script>
 </head>
 <body>

 <script>
 // set our baseURL reference path
 System.config({
 baseURL: './'
 });

 // loads /js/main.js
 System.import('main-module.js');
 </script>

 Open your js console.
 </body>
</html>

main-module.ts

import {someVar} from "./some-es6-module.js"

console.log(someVar);

some-es6-module.ts

export var someVar = "Hello World";

tsconfig.json

{
 "compilerOptions": {
 "module": "system",
 "target": "es5"
 },
 "files": [
 "main-module.ts",
 "some-es6-module.ts"
 ]
}

To make it run:

  1. Put all those files into a folder or download them from https://github.com/bersling/minimal-typescript-es6-module-app/tree/master.
  2. Get the typescript compiler and run tsc.
  3. Start a server with python -m SimpleHTTPServer and see the app at 127.0.0.1:8000

Long to Base64 and Base64 to Long in Java

The following code converts a base64 String to a long and vice versa.

private static final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
public static String encodeBase64(long v) {
    char[] a = alphabet.toCharArray();
    v = Math.abs(v);
    String s = "";
    for (int i = 0; i < 11; i++) {
        long val = v & 63;
        s = a[(int) val] + s;
        v >>= 6;
    }
    while (s.startsWith("A") && s.length() > 1)
        s = s.substring(1, s.length());
    return s;
}
public static long decodeBase64(String s) {
    char[] a = alphabet.toCharArray();
    Map<Character, Integer> map = new HashMap<>();
    for (int i = 0; i < a.length; i++)
        map.put(a[i], i);
    char[] chars = s.toCharArray();
    long v = 0;
    for (char c : chars) {
        v <<= 6;
        v = v | map.get(c);
    }
    return v;
}