Menu

A Conventional Blog for Convention Based Coders

Month: March 2016

We just experienced an uncomfortable couple of days when we discovered that the latest version of every package in our myGet cloud-hosted package server had been deleted!
How did this happen? Surely nobody would manually access each package and delete the latest version?
Well, it turns out to be example of dangerous client-side filtering combined with a seemingly innocent action be a developer.

At the top of the feed screen we see the following:

OK, so the button on the right deletes the package (although it’s not clear whether it deletes the package below or the package above), and the one at the top deletes the… er… the… everything?

Ah, so clicking it shows a list of deletion options (although why would you ever want to delete the latest version of every package in your repository?)

OK, so what if we type something in that search box in the top right? After all, I only want to work with the Korzh.Net package…

Well, here we have an example of client-side filtering abuse. It’s great that we can narrow things down on-screen to make searching through long lists manageable, but of course people are going to click the top delete button to delete the only package on-screen, and remove the latest (or all versions) of every package in your repository!

So, if you plan to have client side search, please make sure you disable any actions that apply to the unfiltered set.

There are dozens of javascript based spinner libraries available, but given their simplicity I find it easier to create my own.
The key thing is the css that both displays the spinner and blocks the user from clicking other controls on the screen.
This can be divided into two pieces; the blocker:

So how do we use this? We want to be able to enable or disable the spinner from any Promise anywhere in our code, so we’ll simply inject a common busy service with a flag that we can bind our busy functionality to:

JavaScript

1

2

3

4

5

exportclassbusy{

active:number=0;

on(){this.active++;}

off(){this.active--;}

}

and in our base router view we can add the spinner code:

XHTML

1

2

3

4

5

6

7

<template>

<div show.bind="busy.active">

<div class="spinner"></div>

<div class="spinner-blocker"></div>

</div>

<router-view></router-view>

</template>

To use this in a lengthy operation we simply call
busy.on() and
busy.off()

Make sure you always make these calls within a Promise! There’s nothing more frustrating to a user than seeing an error with an infinitely spinning symbol blocking their input!

Here’s an example of displaying a spinner while authenticating a user:

The way Aurelia tracks dependencies on properties is awesome, but there are times when we want to know in code if a property has been updated. Sounds simple, yes? Unfortunately there are a few hurdles.

Firstly, the convention based way of doing this in Aurelia is to create an ‘xxxChanged(newvalue, oldvalue) ‘function on our VM that is auto-magically called whenever property ‘xxx‘ is updated. Unfortunately these changes are restricted to the topmost property, so if we have
currentuser={name:'fred',age:'25'} then we won’t be alerted if the user’s age is changed.
Does this mean that we don’t get binding of the nested element? No, certainly not. Anywhere on the screen where we bind to
${currentuser.age} , the value will be updated correctly, as the act of creating that template binding creates an observer to reflect changes within the bound DOM entity.

Secondly, if we’re observing the three properties of our currentuser (the root and two children) what happens if we replace the object with a new instance, such as
currentuser={name:'Oliver',age:'6'} ? We still have two observers linked to the old object, and these have to removed and disposed of.

Thirdly, we need a way of manually disposing of the observers when we’re finished, or in case we make significant changes to the tree and need to regenerate the observation collection

What we need is a method of observing all of the nested element, and receiving a callback when any of them are modified.

So, with a simple(ish) piece of recursive code we have a means of tracking changes to entities, and having a callback that even supplies the property name that was changed.

The call to observe() returns us a parameterless disposer that we keep track of and can call at any time to dispose of all our observers.

Subclassing is very useful, but how do we link it to our dependency injections?

Aurelia assumes all injection will be against the current object, so we have two options. The first is that if we want to use constructor injection and inject those objects into the base class, we must supply them from the inherited class.

This is fine, as the base class knows nothing of the subclass, but it does mean that when developing the subclass we must replicate the injected object types.

e.g.

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

import{Container}from'aurelia-dependency-injection';

import{DialogService}from"aurelia-dialog";

import{DialogController}from"aurelia-dialog";

import{api}from"../services/api";

exportabstractclasspersonBase{

public name:string='Bob';

constructor(public dialogService:DialogService,

public controller:DialogController,

public api:api

)

{

}

Anything deriving from this must perform the dependency injections and call the underlying base class:

The second method is to read the items directly out of the container in our base class, using

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

import{Container}from'aurelia-dependency-injection';

import{DialogService}from"aurelia-dialog";

import{DialogController}from"aurelia-dialog";

import{api}from"../services/api";

constructor()

{

this.dialogService=Container.instance.get(DialogService);

this.controller=Container.instance.get(DialogController);

this.api=Container.instance.get(api);

}

Which you choose to use is largely a matter of preference as behind the scenes Aurelia is using aspects of the second method to implement the first, but there are some fundamental differences that may prevent some plugins working, such as aurelia-dialog. My preference is to use the first method, ensuring current and future compatibility with plugins.

As a final point, it’s worth noting that we can always refer to the base class from our subclass using the ‘super‘ keyword, allowing us to extend the existing page lifecycle:

JavaScript

1

2

3

activate(params){

returnsuper.activate(params);

}

This is one great way to improve code re-use, but beware of growing your base classes, and always consider whether composition might be a better option than inheritance.