Copying static files into build directory with Angular

This is probably obvious for Angular aficionados and aficionadistas but I found how to copy static files into the output directory of an angular application non-obvious.

To do it go to angular-cli.json in your project root and add the static file to the assets collection thus

And it places it nicely into the output folder which is dist by default. I found this useful when using a web.config file to set up some URL rewriting rules in an IIS hosting scenario i.e..

Just though I would break it out of that post and flag up how to do it when I had a spare 10 mins between cleaning the bathroom and taking the daughter to swimming lessons (too much information – sorry).

Hosting Angular in IIS under an existing website

I recently had cause to put an Angular application a IIS sub application under an existing .Net website so effectively they share the same host url. It took me longer than it should have done – I made heavy weather of it. Some issues were just fiddly and took some working out. Some issues I had were the result of my own sub-optimal performance in this technical area (stupidity). It was Saturday afternoon so I’m allowed sub -optimal performance in my own time.

Tutorial

There is already a good tutorial here. So I’m not proposing to go through it step by step, Instead I’ll quickly outline the basic steps then point out where I went wrong. I suffer so you don’t have to.

Motivation

Just briefly – my motivation for doing this was to have Angular running under the same address as the API it was calling.

So

Is called by an angular app under a virtual directory at

This is to avoid Cross Origin Scripting Issues in my own environment. I know there are other ways to do this – but they either

  1. Never worked
  2. Were too invasive to implement on the API side (for a spare time demo project)
  3. Did work then frustrating stopped working

So I bit the bullet and moved Angular under the API project where it is always going to work for me i.e. they use the same host url so are no longer cross origin.

Create the Sub Application

So very briefly – ceate a sub application under main application to get this configuration

Point virtual directory to Angular app and browse. Boom – It doesn’t work!

Error 1: Using a .Net App pool

First issue is this yellow screen of death

The exact error will vary but essentially the angular application complains that it is missing assemblies, handlers, modules etc… It wants to be a .Net application. It doesn’t need to be.

When setting up the new application the default will be a .Net integrated application pool

To stop it behaving like a .Net app – create a new app pool with .Net CLR version of ‘No Managed Code’

Assign this to the new angular application in IIS and the site is no longer a .Net wannbe. The YSOD is gone.

Error 2: Pointing to the wrong folder

No yellow screen of death, instead the application is entirely blank. This is where I was being particularly sub-optimal. So I pointed it to my angular application at

This is never going to work. Angular builds into this directory by default

Point the sub application here. Why I thought this would magically work I’ve no idea. Although IIS had stopped behaving like a .Net site, I clearly carried on thinking it was one and pointed to the root folder as I would a .Net site. 15 minutes of my life working this out that I am never going to get back. Oh well.

Error 3: Correcting Angular script references

So run the app again and sadly it is still blank. This time if you look at chrome developer toolbar or similar you will see a lot of 404 errors

What’s going on here is that Angular is still behaving as if it is loading all scripts from the root website. To correct this

  1. Use base href element in the root index page i.e.

1. Change the ng build command from

to

This will point Angular to the right direction i.e. looking at the dist folder the script references have changed from

to

Which is correct for our sub application.

As a side note – I always forget these kind of command lines. To avoid the need for additional brain friction use the npm start command to run the ng build command with the extra parameters. So go to packages.json in the root directory of your angular app and change the npm start node under scripts to the build command i.e.

Now to build the app use

And the build command runs with the correct params.

Error 4: Refreshing page causes 404

If you are using routing you will find that refreshing a page when on a route (i.e. demo-app/Angular/page1) will give a 404 error, To resolve this one

1. Install Url rewrite

2. Include a web.config page into your src folder with these url rewrite rules

3. Include the web.config file in project assets. Go to .angular-cli.json and add web.config to the asset node like so

If you omit this step then the web.config won’t be copied over to the dist folder on build. If you add it to the dist folder manually then it will be deleted on build so you won’t be any further forward.

Once all these steps are done, refreshing on a route this will reissue the request up to the base url which will resolve correctly.

Finishing up

Now the angular app runs nicely under a sub application in IIS and my Cors problem is no longer an issue. There are a couple of disadvantages to running it this way

  1. Hot reloading of the application on rebuild doesn’t work
  2. Related to this – the application sometimes caches and a hard refresh of the browser (ctrl, F5) is sometimes needed to kick it back to life.
  3. When refreshing a page it will redirect back to the root so you lose whatever route you are on so

Refreshed becomes

Which may or may not be what you want

These are probably resolvable but when I got my development environment to this point, I declared loudly to all with ears to hear – Job done!

Useful Links

https://docs.microsoft.com/en-us/iis/extensions/url-rewrite-module/creating-rewrite-rules-for-the-url-rewrite-module
Url Rewriting module in IIS – official microsoft page

https://blogs.msdn.microsoft.com/webdev/2006/06/30/part-1-of-3-creating-sub-projects-in-iis-with-web-application-projects/
Setting in sub applications in IIS – detailed tutorial

https://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Wiki page about CORS which was causing me all the problem in the first place

 

Yet Another Free JavaScript Book: Angular 5

As part of my unplanned and unasked for blog series – Free JavaScript books, here is another. So introducing ‘Angular 5: From Theory To Practice: Build the web applications of tomorrow using the new Angular web framework from Google’ by Asim Hussain. It’s not exactly vanilla JavaScript as such – it’s Angular 5 and TypeScript but we’re all friends here so I’m lumping it in with the other free JavaScripts books I’ve written about.

And it’s a good one. Pitched at the right level, good quick start chapter so you can see how it all fits together early on and a nice primer on TypeScript in chapter 2. So, how much for hundreds of pages of Angular goodness delivered to a Kindle device? Well to you Madam/Sir, it is zero pounds, shillings and pence or nada dollars if you prefer. Oddly, if you are trying to get this on Australian Amazon then you are out of luck – clearly the bits and bytes can’t travel that far (though a VPN connection might help in that circumstance).

But Amazon Australia not withstanding, this book is worth the money. I’d even go further – this book would be worth the money if Mr Hussain ever decides to charge for it. Thank you Asim.

Angular pipe to truncate text to the nearest whole word

The problem

I want to truncate text in Angular 5 using a pipe. I don’t just want to chop the text up inbetween words. I want to truncate to the nearest whole word. And I want a ellipses on. I want it all. So the following text as an example

Mind precedes all mental states. Mind is their chief; they are all mind-wrought. If with an impure mind a person speaks or acts suffering follows him like the wheel that follows the foot of the ox.

Truncated to a length of not more than 150 would be

Mind precedes all mental states. Mind is their chief; they are all mind-wrought. If with an impure mind a person speaks or acts suffering follows…

I want that – and as luck would have it is actually a nice quote. Purely coincidental of course.

Starting off

First let’s use angular cli scaffolding to get us the base pipe. So open the command line and run

Or if you prefer

And the following js file pops out

Nice start. The pipe metadata tells us that to use it in the html page we will be using the truncatetext tag. It’s pretty obvious where our implementation is going to be.

The Implementation

So filling out the implementation gives us

So a bit at a time. The signature has changed to

Value is the string that is to be truncated. Length is our target (maximum) length. It returns a string which is the truncated text. There is a bit of parameter checking then

I’ve taken the view that the biggest word I’m likely to deal with is

Pneumonoultramicroscopicsilicovolcanoconiosis

So it’s 45 letters plus 5 for any spelling mistakes for a 50 character margin. (I’m ignoring the 189,819 letter protein name that someone unearthed – I guess biochemists need to use this Angular filter with caution).

So I truncate at my desired length plus 50 then nibble backwards at each space

Until I get to my length then glue on the ellipse and return it out. The only other thing Is

A sprinkle of regex to nibble off any comma, question mark etc.. What I don’t want is a result like

Mind precedes all mental states. Mind is their chief;…

It just looks weird.; I want

Mind precedes all mental states. Mind is their chief…

Much better.

Using the pipe

So to actually use the pipe in the component we need to declare it in the app.module e.g.

If you’ve use the angular cli command then that would have been done for you. Then to use in the component it is simply

And then that is it – my text is truncated in my angular app and looks something like this

Lovely filter; lovely quote.

Variant for truncating to a small length

It’s an edge case for me but there is the case where the filter is set to a (stupidly) small value e.g.

Taking into account the ellipses, the logic would be that the entire string evaporates to just the ellipse or perhaps nothing. I don’t really want that so this filter will return the first word with an ellipse as the minimum return value i.e.

If you want the behaviour where the output strictly adheres to the length or less then it would be something like ..

So it will return the length or less in all cases – if you really want that.

Demo App

As ever the code is on my github site here. It’s part of a bigger app and associated API that generates Buddhist quotes from the Pail Canon. All work in progress but I quite like it.

Useful Links

https://angular.io/guide/pipes
Official documentation for angular pipes. Useful

https://en.wikipedia.org/wiki/Longest_word_in_English
Biggest words in English for edge cases and general marvelment

https://www.accesstoinsight.org/tipitaka/kn/dhp/dhp.01.budd.html
The example text is the first verse of the Dhammapada -original translations by Acharya Buddharakkhita. The first verses are all in pairs so the example text with its partner is ..

Mind precedes all mental states. Mind is their chief; they are all mind-wrought. If with an impure mind a person speaks or acts suffering follows him like the wheel that follows the foot of the ox.

Mind precedes all mental states. Mind is their chief; they are all mind-wrought. If with a pure mind a person speaks or acts happiness follows him like his never-departing shadow.

Tremendous – one of my favourites.

A web.config implementation for AngularJS

It’s said that when learning a new language or framework it is best to approach it fresh, with no preconceived ideas from other languages. So completely ignoring that advice here is my implementation of an ASP.NET web.config file in AngularJS.

I’m used to squirrelling away my config in one external file and I want to do that again in AngularJS. Really it’s the appSettings part of the web.config file that I’m implementing but the point is that all my config for the application is in one file that I can use throughout my application. I like it in .NET and I want to do it again here.

The implementation

App.Config.js

The first step is to implement a config object in an external file like so…

We have just 2 config items at the moment, the root of the API and if it is in debug mode or not. In the normal run of things I wouldn’t want to pollute the global scope with JSON objects. I would wrap them in an IIFE. However this is a special case as it is genuinely global so I’m explicitly placing it in the global scope i.e. using the window object.

As it is an external file I need to remember to reference in the main application page.

App.Module.js

The next task is to reference the config in the main application file – app.module.js in this case. This is how I’m going to make it available throughout the entire application. Strictly speaking I don’t need to do this. As it is on the global scope I could leave it like that and directly reference it via the window object. I’d rather not do that. It’s going to make unit testing problematic in the future and anyway I don’t like it. Instead, I’m going to use the app.constant property in the main app.module file thus

My naughty accessing of a global object is here and nowhere else. The config object is placed into app.constant which is then available throughout the application via dependency injection. I could have used app.value and it would work in much the same way. However I’m never going to change these values during the lifetime of the application so the constant property is more appropriate.

Consuming the config

The config is then available via dependency injection in controllers, services, directives e.g.

In a service

The consumption in a service is the same. The use case here is a service can use the config to set the API url which could, should and will change in different environments.

In a directive

I’ve previous blogged about a debug panel that can be toggled on and off. In that post I used a query string parameter to turn the display of the debug information on and off.  In truth I don’t really like that. This is the debug panel directive implemented with the web.config style config. As before it is injected in and it does a bit of DOM manipulation to remove the panel in the link method if debug is on. I prefer this way rather than my crazy query string implementation from before.

Deployment

One of the reasons that I like external config files is that I can have different settings in different versions of the files. I can then use some sort of task runner or deployment script to swap them out as it moves through different environments. So I could have the different app.configs in my project i.e.

  • app.config (standard development one)
  • app.devtest.config
  • app.qa.config
  • app.preprod.config
  • app.prod.config

I can then delete the app.config file and rename the environment specific file so it is picked up in different environments. So when deploying to QA I would ….

  1. delete app.config
  2. rename app.qa.config to app.config

And as if by deployment magic I get different settings in QA. I currently use a bunch of PowerShell scripts to do this so it’s all automated but it can be done with whatever script or tool is most familiar or fashionable or nearest to hand.

Alternative implementations

As always, I’m not claiming that this is the best implementation for consuming application config. Global scope and config is going to be something that can be done in any number of ways. In fact I can think of several just while sat here typing in my pyjamas.

Global objects

I could just access the config directly wherever I like by using the global windows object like so..

I personally don’t like having the windows object scattered through my code but it could be done. It’s not going to work well with any kind of unit testing though so unless you’re a no test kind of developer it’s probably best avoided.

Global scope

We could use $rootScope instead of app.constant to stash the external config file there. So accessing it would be a matter of grabbing the config from $rootScope thus

I still like the idea of only the config being available in the method. I just get what I need, not the entire rootScope – that said this would work perfectly well.

Log Provider

This isn’t a complete replacement but it’s worth noting that debug config could be implemented through the $logProvider component if we wanted. To toggle on and off we would do this

It’s not a complete replacement but in the interests of full disclosure there are other (better??) ways to get debug information in and out of angular that have their own config.

Useful Links

https://ilikekillnerds.com/2014/11/constants-values-global-variables-in-angularjs-the-right-way/
Article on app.constant vs app.value

http://stackoverflow.com/questions/6349232/whats-the-difference-between-a-global-var-and-a-window-variable-in-javascript
Useful stack overflow question comparing the windows object and global scope.

http://odetocode.com/Articles/345.aspx
Ode to Code on appSettings and web.config. That’s the part of the web.config I’m aiming to emulate in this post.

https://thinkster.io/egghead/testing-overview
Testing with angular. Here’s what you might miss if you want to implement this with a global object.

http://stackoverflow.com/questions/18880737/how-do-i-use-rootscope-in-angular-to-store-variables
Using rootscope to store variables

https://thinkster.io/egghead/index-event-log
logProvider examples – about halfway down.

Troubleshooting blank pages and render failures in AngularJS.

An odd thing happened this weekend when I was tinkering with some code while pointedly ignoring my daughter and parenting responsibilities generally.

The Task

Put in a new directive to implement a reusable panel to display error information. Not ground breaking stuff by any means. The html is simple enough

Very bootstrappy as usual. Reference the directive on the view thus

Happy days – a lovely reusable error panel.

The Problem

Sadly it isn’t to be. The previously functional page becomes entirely blank after the directive.

Badly formed directive

Unhelpfully there is no errors in the console and viewing the HTML source does nothing for us since it is a single page application.

The Solution

The problem is the use of self closing tags when referencing the directive. Referencing the directive with an explicit closed tag resolves the issue. Example – use this markup

And the page springs back to life

Well formed directive

Relief all round. Fortunately I found the solution pretty quickly (though I still continued to ignore the daughter). It’s the sort of error that can wasted hours if it hits on a Friday afternoon when you are feeling generally depleted.

Actually the use of self closing tags isn’t that helpful in HTML5. I’ve got into the habit of using them but looking into it more deeply it’s actually a bad habit. They are valid but optional in HTML5 for void elements but invalid for non-void elements. Since they are either optional or invalid its best to avoid them and write out the tag – particularly as it causes obscure issues like this.

Useful Links

http://stackoverflow.com/questions/3558119/are-self-closing-tags-valid-in-html5
Good discussion of Stack Overflow about HTML5 and self closing tags.

https://docs.angularjs.org/guide/directive
The official documentation for AngularJS directives if more information is required.

 

 

Simple Debug Panel for AngularJS

I am aware that there are many many other ways to get debug information from an AngularJS application but that’s not stopped me implementing another one. I do actually find a customised output of JSON objects useful particularly when working with deep object graphs. The implementation also is useful as a worked example of a couple of AngularJS principles.

The Demo Application

The demo application is a bookshelf application that searches the google book API and enables the user to add books to their own library. This is my ‘go to’ demo application that I’ve implemented a couple of times in different frameworks. This one is using the MEAN stack and the source code can be found here.

The Problem

When I search the google API I get a very large complex JSON object as the output. I want to know what is in there as I’m saving bits of it in my own database and might be interested in other bits. I want it displayed but easy to toggle on and off. I’m ultimately going to read something from the query string to do this as it is easy to toggle with minimal fuss.

When it’s finished it’s going to look like this…

debug panel
Google Bool API results displayed in debug panel

I’m going to use bootstrap for styling throughout as I’m not hugely concerned about how it looks – it’s just got to be reasonably neat. So its bootstrap classes throughout I’m afraid.

The Solution

The solution is going to demonstrate the following

  1. The use of directives in AngularJS
  2. Using global values and config
  3. Setting globally accessible values from the query string.

    Step 1: Implement a debug panel

    The initial implementation is directly on the search page. When I do a search I want to see the following debug output

    debugpanelonsearch
    Debug panel displayed on book search page

Before I do a search I don’t want to see anything.

The implementation is

The scope has a property SearchResults with a giant json object direct from the GoogleAPI. I want to show this. I use the json filter to prettify the result and it’s wrapped in pre tags so it displays like code. The ng-show attribute hides it if the searchResults is null or generally falsy which is what I want. That’s pretty good and works for me.

Step 2: Make it a directive so it can be reused

Now I want this on every page and I want it to display anything I want not just the searchResults. I want it to be generally useful. To achieve this I’m going to use directives which allow me to include fragments of HTML across different parts of my site. I now want it on the book details page as well.

The first job is to extract out the debug panel into a separate html file and to remove the dependency on searchResults. The debug panel html is extracted and saved into its own file at

And it looks like

This is the contents of the entire file now. I’ve removed the binding to searchResults and I have now got a property called ‘display’. This is any JSON object I want to display in my results panel.

Next job is to tell my angular application about my new directive. So I create a new JavaScript file and put this in

This does a few things. It tells angular where to find the html fragment for display via the templateUrl property. More interesting it also uses scope isolation to feed in the JSON object I want to display.

The scope property is the link between the page and the directive. I can insert my parent page scope into an attribute called display and this becomes available to the directive. It breaks the hardcoded dependency on the parent scope and makes it all more flexible. The ‘=’ in ‘=display’ tells angular it is an attribute.

That’s probably not hugely clear but finishing the example should help us. The last step is to reference the directive on the book details page. I need to remember to include the script

Then the directive is referenced as markup which looks quite neat

So the display attribute is bound to the book property which is then fed through to the debug panel and displayed. I can put anything into it not just searchResults as before.

debug panel on book details
Debug panel displayed on book details page

I can now go back to the search page and implement the directive in the same way.

And that will display my search results in prettified json which I quite like. It’s even better now and I am mentally slapping myself on the back. However I’m not finished. I don’t always want to see the debug panel. Sometimes I just want to see the page as it will be when it goes live with no debug information at all. I want to be able to toggle it on and off with ease.

Step 3: Using a global setting to toggle the debug panel

I have ambitions for my BookShelf demo site to be truly huge; a site which will make eBay look small. To that end I don’t want to have to turn my debug panel on and off manually everywhere it is used. I want one point of control.

I’m going to set up a DebugOn flag when the application initialises. For this I could use a global constant like so

However (spoiler alert) I’m going to want to amend them later on so a global value is more the way to go. I’m setting this when the app initialises so it will be

I can use the built in dependency injection to access the global variable in any service, filter etc.. so I’m going to use that to grab it in the directive script …

The directive has become a bit more complex but it’s not too terrifying. I’m taking the DebugOn value as a DI injected parameter – very standard Angular stuff. I want to hide the debug panel if it is set to 0. In essence I want to change the DOM if the DebugOn variable is 1 and the link property enables us to do that.

The elem parameter is a collection of all the directive element outputs in the app at that time. For the debug panel it will be one but I will be good and iterate through it anyway – we just obliterate the innerText and thus hide them from the user.

Now we have done this turning the debugging panel off becomes a simple matter of amending the value of DebugOn variable in one place and restarting the application.

Just what I wanted.

Step 4: Using the query string to toggle the debug panel

But it’s not enough. It never is. I’m not satisfied with amending the application – I want to just pop something on the query string, have my application pop into debug mode and have my debug panels spring into life like desert flowers in the rain. I want it and I can have it.

Should turn on the debugger but as I’m navigating around my single page application my querystring is going to disappear. I could maintain it but I don’t want to – it seems like hard work. So I’m just going fall back to some good old fashioned JavaScript. The full url is available in

So I’m going to use a couple of functions to grab the value and put it in the global variable

And the setting of the debug variable becomes

And done. I done even need to change my app to get the debug panels on. A quick fiddle with my querystring and there they are. Lovely.

Further Development

As much as I like the query string idea I wouldn’t want to see it in production. As an immediate project I would want to disable this in prod environments. It’s not hard but needs to be done. I’ve got other ideas around multiple panels, debug levels and improved display but I’ll leave those for another day.

That’s it – end of post other than notes. Happy New Year everyone for 2017.

Full Script

There is a bunch of code here so to aid the discerning coder – this is the all code needed for the debug panels

directive.debugDisplay.js

debugDisplay.html

utils.js

app.module.js

Note about Immediately Invoked Function Expressions

I haven’t wrapped all my examples in an IIFE. This is just to save space and reduce nesting in the examples. Just mentally put them back in if they are absent i.e.

Useful Links

AngularJS directives
https://docs.angularjs.org/guide/directive

Scope isolation
https://thinkster.io/egghead/understanding-isolate-scope

AngularJS Constants and variables
http://ilikekillnerds.com/2014/11/constants-values-global-variables-in-angularjs-the-right-way/

Quick explanation about IIFE
http://stackoverflow.com/a/8228308/83178

The getParameterByName function is from the incredibly highly upvoted answer on Stack Overflow
http://stackoverflow.com/a/901144/83178

Google Books API as referenced throughout demo code
https://developers.google.com/books/

Simple String Concatenation Filter for AngularJS

I’m currently tinkering around with Angular JS. I’ve always liked JavaScript and since there is currently one or two (thousand) JavaScript frameworks around I thought I would have a go at the Angular. It wasn’t immediately obvious how to cleanly concatenate strings for display so I wrote a filter and it works quite nicely. As ever I’m not making any claims for this to be technically brilliant but it does work, I wrote it with my own coding fingers and I like it.

The Demo

The demo system for this is a simple search for books using the Google Books API. The results display on an infinite scroll. That’s totally irrelevant to this but again I like it. The demo project code is on github at https://github.com/timbrownls20/BookShelf.MEAN.Stack

The Problem

Books have multiple authors. The Google API returns them in an array i.e.

We display them on the view with a simple binding

But unfortunately the display looks rubbish

no-string-concat

The Solution

We could display them correctly by putting a bit of looping logic in the view but I see enough abuse of views in my day job (and I’m guilty of some of it myself) so I would rather not continue view abuse in my spare time. So let’s whip up a filter. It will be cleaner and reusable.

To implement create a file called filters.js and pop in this

It’s embarrassing straightforward. An array and a delimiter in, join and return. We added it directly into our angular application which is imaginatively called ‘app’. It’s then available to be called in the view with a PowerShell style pipeline i.e.

Don’t forget to reference the new file in the view (html page)

And that’s it, everything looks a lot better.

string-concat

It’s available to use generally in the application whenever we need to concatenate strings. Lovely and easier to implement than I remembered.

Useful Links

Documentation for AngularJS filters can be found at
https://docs.angularjs.org/api/ng/filter/filter

and an end to end tutorial including filtering is at
https://docs.angularjs.org/tutorial/