Archive for the 'Web' Category

February 3rd, 2021
6:36 pm
404 errors on load when angular 11 app deployed to a domain subdirectory

Posted under Angular & Uncategorized & Web

As above, a webpack build in angular 11 which loaded and ran fine locally failed to load when deployed to a subdirectory of a domain hosted using cpanel.

This post here goes into the cause of the issue. The simple solution in my case was to change <base href=”/”> in index.html to <base href=”./”>. This then supports any subdirectory

In fact upon reviewing some past angular code, it appears that previous projects did include this change, but it was not clear if I had done this or if it was by default, and I could not remember.

This fix resolved the issue. Note that as per the post, there are build switches which allow changing of the href, but my change did not get overriden, and works fine for both development and prod situations, so I just left it in permanently.

Comments Off on 404 errors on load when angular 11 app deployed to a domain subdirectory

January 27th, 2021
6:34 pm
Creating and compiling a Custom PrimeNG 11 theme deployed as a static asset

Posted under Angular & PrimeNG & Uncategorized & Web
Tags ,

This follows on from this earlier post for Angular 6.

PrimeNG has for some time removed support for legacy themeroller themes and added their own architecture and theme editor. However, for the first time, the theme editor and the SCSS theming interface/standard SCSS files are no longer open source, but are a paid for option. The rest of the component set, including the delivered compiled css for all the standard themes, is available as open source as before.

Therefore, having considered the options, I elected to take a standard theme that was close to what I needed and edit its css directly. This is suggested as an option by Prime for small changes, but it is possible that later changes to the theme architecture could require theme changes as we are editing the compiled css. I decided that the risk and rework that might be needed was small, so have taken this route.

My policy on this is to copy the theme files to a new theme folder under assets/resources/themes/, and then to rename the theme.css file to theme.scss, as the compiled css is also valid scss. This then allows me to add my own variables as required for theme colours etc. to avoid duplication. The intention is to minimise alterations to the original theme, so I would only add variables where I had made changes, to minimise any rework if I had to take a new version of the standard theme and add my changes again.

Whilst doing this, I noted a warning that node-sass, as used previously, is now deprecated. I therefore switched to sass, as per this stackoverflow post, using npm uninstall -g node-sass followed by npm install -g sass. This worked fine, and my changes to the existing compilation script in package.json (also allowing multiple themes to be compiled) were as follows:-

 “scripts”: {
“ng”: “ng”,
“start”: “ng serve”,
“build”: “ng build”,
“test”: “ng test”,
“lint”: “ng lint”,
“e2e”: “ng e2e”,
“scss”: “npm run scss1 && npm run scss2”,
“scss1”: “cd src/assets/resources/themes/salient-new && sass theme.scss:theme.css –source-map .”
“scss2”: “cd src/assets/resources/themes/salient-new2 && sass theme.scss:theme.css –source-map .”
},

 

Comments Off on Creating and compiling a Custom PrimeNG 11 theme deployed as a static asset

January 13th, 2021
3:42 pm
404 error when loading external config script in angular 11

Posted under Angular & Uncategorized & Web
Tags ,

In angular 6 I was able to load custom static scripts, either via script tags in index.html, or dynamically, by placing the scripts in the project root (when using ng serve), or in the dist/projectname folder when running the built application. I originally used this for externalised configuration per my original post here, initially using script tags in index.html, and later using dynamic script loading via APP_INITIALIZER, which allowed dynamically named config files derived from query string parameters, and also early dynamic loading of external scripts such as for Yoti.

However, in angular 11, these use cases all gave 404 errors on the script. Posts such as this one here pointed to the need to place static files under the assets/ folder (although the post used an earlier angular version than 6, so I would expect it to work). I tried this, and both the static and dynamic use cases then worked correctly. I suspect that this is due to changes in the packaging when building and using ng serve. I retried a simple new project with a static script called from index.html, both under 6.1.7 and under 11.0.6. Under the older version, scripts in the root folder worked, but under 11.0.6, I had to place the scripts under assets (or in a subfolder of assets). This clearly demonstrated and resolved the problem.

Comments Off on 404 error when loading external config script in angular 11

January 5th, 2021
6:15 pm
Installing/running multiple Node/Angular/primeng + showcase versions under windows

Posted under Angular & PrimeNG & Web
Tags ,

I needed to upgrade node/angular/PrimeNG/primeNG Showcase to the latest versions (Node 15.5, Angular 11, PrimeNG 11) , but I also wanted to be able to maintain projects on older versions using Angular 6.

This post details how to do this with nvm under Linux, but an alternive nvm implementation is needed for windows. This is detailed here, and the git repo for this version with full instructions is here . I uninstalled the existing angular cli/PrimeNG via npm uninstall, and then removed my node installation via control panel.

Next I installed nvm per the above post for the windows implementation. Per the above post for the Linux version, I used nvm install to install node versions 10.4.0 and 15.5. I then selected each in turn via nvm use, and for each version, I installed the desired angular/cli for that version globally in the standard way, using for example npm install -g @angular/cli@6.2.2 for the legacy version. Note that using -g in this case installs globally for the currently selected node version only, so when you switch/select the current node version with npm use, you also automatically select the angular/cli version that you previously installed with it.

Having done this, and as per the above posts, you must remember to select the desired node version with nvm use in each command window or batch file that you use. The version is not selected for a project directory, but is per command window/process.

I was then able to use both the latest angular/primeNG and the legacy ones, and could build and run with both on the same machine.

One issue I hit with primeNG when performing npm install on the latest version was a bug in the latest version of node: “Cannot destructure property ‘name’ of ‘node’ as it is null.” This bug is detailed here. Per the post comment by Mika Bertels, I reverted to npm 6 using npm i -g npm@6. In my case, npm gave a file already exists error, so as hinted by node I used the –force flag to force the reversion of version. This worked fine, and my npm install of primeng worked successfully

Per the instructions here, the primeng 11 can just be installed and then run with ng serve, and I did not hit any issues with theme building etc. which I did with earlier versions, presumably due to all the themeing changes. Note also that this setup guide for primeng explains how to install primeng and primeicons when using with your own project – I did not need to do this initially as I was just running the showcase.

 

Comments Off on Installing/running multiple Node/Angular/primeng + showcase versions under windows

December 24th, 2020
11:40 am
Angular changes DOM again after calling ngAfterViewInit

Posted under Angular & Web
Tags , ,

Originally I used ngAfterViewInit to perform some custom DOM changes in a component (adding a default title to certain dynamically added anchor tags).

Unfortunately this resulted in weird behaviour whereby the changes did not appear in the DOM. It appeared that the DOM was being rebuilt again after the lifecycle hook had been called, as initially in debug the changes could be seen on the page, then they instantly disappeared.

Switching to using ngAfterViewChecked resolved the problem, as noted in this StackOverflow post. Whilst there are efficiency issues to consider here, it is obviously essential that the lifecycle hook used is guaranteed to be called every time the DOM is updated. Note also that the first time through flag used in the above StackOverflow post did not work – clearly the DOM was still being changed after the first call to ngAfterViewChecked, so the first time through flag was dropped. This other StackOverflow post also discusses the same solution to the problem.

Comments Off on Angular changes DOM again after calling ngAfterViewInit

May 12th, 2020
9:35 am
Template Strings in configuration data – IE11 issues

Posted under Angular & TypeScript & Web

I was leaning towards using .js files rather than strict JSON for configuration data (and therefore loading them dynamically via a script tag). This allows some additional intelligence in the files that you could not get with JSON.

One point of interest was to use template strings via backticks to allow parameter substitution, as I have detailed in this post here.

The problem with this approach is that IE11 will not support it and cannot therefore load the .js file. Whilst this could be worked around by using typescript and transpiling, this is clearly not ideal and not the focus for a configuration file – I wanted it to be plain edited text.

As in the target use case I did not need placeholder substitution, my workaround was to use ordinary single quoted strings with continuation appended to each line as ” \”. This worked fine in IE11.

This does mean, however, that for substition and other advanced tricks, you would need to take the other approaches noted in the above post if you wanted to support IE11.

Comments Off on Template Strings in configuration data – IE11 issues

May 8th, 2020
7:40 am
Dynamic String Interpolation in Typescript/Angular

Posted under Angular & TypeScript & Web

There does not appear to be a truly dynamic string interpolator available, such that the string template with placeholders can be just a string obtained from anywhere, and then used as a template in the way that e.g. java does with String.format() and MessageFormat.format().

There are 2 ways around this:

1/ Using a lambda allows delayed evaluation of the standard string interpolator as you can pass parameters to the lambda.

If the configuration data containing the templates etc. is a .js file rather than pure JSON (in the way that I do my configuration), it is possible to actually store the lambdas in the configuration data in ‘JSON-like’ object literals. Obviously care is needed with error handling etc. when loading the .js file. This trick is detailed hereThis is a nice approach in that you can use all the standard string interpolation tricks, and also others such as ternary expressions etc., in your configuration data, making it as intelligent as you need to. The downer is that it is no longer pure JSON, but it can be loaded dynamically from a .js file. Another issue with this approach is that it is not supported by IE11, and so cannot be used if this is a factor, as per my other post on this here.

2/ Roll your own template interpolator. This approach is detailed here.

This allows your configuration/template data to be stored as pure JSON. However the downside is that you are rolling your own solution. As a comment points out in the above post, it is perhaps surprising that between Typescript and Angular there is no out-of-the-box solution for this. Whilst the built-in interpolation can be made flexible as detailed in 1/, the approach taken by Java using e.g. String.format() and MessageFormat.format(), whereby built in libraries provide the support at run time, does give more flexibility in this regard. Whilst other templating libraries might be used, such as Handlebars or Mustache, it is undesirable to load one of them as well in an Angular app as Angular has its own templating (albeit with the limitations discussed).

 

Comments Off on Dynamic String Interpolation in Typescript/Angular

April 16th, 2020
6:15 pm
CouchDB view – duplicate keys vs arrayed keys

Posted under CouchDB
Tags

So far when emitting multiple docs I have used arrayed keys containing ordinals to clearly define the order, as per this post here, where the key was complex and already arrayed.

In another example, I was just searching a view on a string ID and returning a couple of docs (via _include_docs), so I had the option of returning the same key for each doc, which is supported. This would allow me to search the view by key – if an arrayed key is used, then a range of start and end key is needed per the trick in the above post, otherwise not all the docs are returned.

In the end I stuck with the original arrayed pattern. Either way would need only a single pass through the B-Tree index. In addition, this recent bug report here seems to indicate problems in returned results when duplicate keys are present, so it looks like duplicate keys are best avoided. The arrayed pattern also gives deterministic order of documents in the results.

 

Comments Off on CouchDB view – duplicate keys vs arrayed keys

March 30th, 2020
12:05 pm
Angular delay reference to *ngIf target until created

Posted under Angular & Web

I had some code which toggled the value checked by an *ngIf, to cause the *ngIf target to be created.

I then wanted, in the same component method immediately afterwards, to refer to the target (which was a ViewChild)  to set focus to it. At that point I got an undefined error, as it had not yet been created and added to the DOM.

This post here details the issue and how to get around it.

Basically, using a setTimeout and setting the focus in its callback solved the problem. The interesting part of the trick detailed in the post was that the timeout could be legitimately set to 0, as all we needed to do was put our callback function on the end of the message queue which would always ensure that Angular change detection runs before the setFocus() call. This worked fine, using the following code:-

// set the state which will trigger the *ngIf to create the focus target
this.autocompleteState = AutocompleteStates.Initial;

// now set the focus as a timeout callback
setTimeout(() => this.searchbar.setFocus(), 0);

 

 

 

Comments Off on Angular delay reference to *ngIf target until created

March 13th, 2020
5:05 pm
Creating a fully trusted Self Signed localhost certificate

Posted under Web
Tags , , ,

I was getting fed up with the various hacks and switches needed e.g. in Chrome to persuade it to use an ordinary self signed certificate to allow ssl for localhost during local development and testing.

My holy grail was to have seamless self signed localhost certificate support, such that the browsers would not complain at all or need any special hacks, but ‘just work’, and without any nasty warnings in the address bar. I wanted to use the same certificate in a Java Keystore for Spring Boot, as well as with a node http-server for serving webpack bundles. After much fishing around, the following solution worked for me.

Summary of Issues found/solved

1/ You can get a self signed cert to be fully trusted locally if you add it to the local computer’s Trusted Root Certification Authorities Store. For windows this is straightforward with the management console – details below in the steps.

2/ In addition, the certificate needs to have a Subject Alternative Name (SAN) defined as localhost, or Chrome will spit it out with a Common Name error. This is a misnomer – the problem is not with the Common Name, it is due to the lack of a correct SAN. Just setting the Common Name (CN) to localhost is deprecated and will no longer work in Chrome.

3/ The Java Keytool can create a keystore containing a certificate with a SAN, using the ext switch. This is detailed here for Java 7 (see the table under the -ext switch). It also works for Java 8 but I found the above docs somewhat clearer than those for java 8. However, I could not find a way to add multiple SAN DNS references, e.g. for localhost and for www.localhost.

4/ I found a way via this post here to use openssl to create a certificate keystore containing the certificate, which I could then import into a java keystore using keytool. openssl  was able to create multiple SAN DNS entries as required. My previous post here links to this post re setting up a Wamp Server, which links to this page re installing openssl.

5/ A trivial gotcha which I hit initially – once you have created and installed the certificate e.g. in the computer’s trust store as above, make sure that this certificate is also the exact one that you are using with all your web servers – in this case, http-server and Spring Boot.

6/ Once all done and working, I could happily use Chrome, IE11 and Firefox without any hacks or switches for self signed certs, and without any hacky warning on the address bar – just the normal black padlock.

Steps to Implement the Solution.

1/ I created a config file for openssl, e.g. req.cnf, as follows:

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = GB
O = Salient Soft Ltd
CN = localhost
[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = www.localhost

2/ I created the certificate and key via openssl using the above config file:

openssl req -x509 -nodes -days 36500 -newkey rsa:2048 -keyout ss-localhost-cert.key -out ss-localhost-cert.crt -config req.cnf -sha256

3/ Import the certificate and key into a PKCS12 store, and then import that store into a java keystore with keytool:

openssl pkcs12 -export -name salientsoftdev -in ss-localhost-cert.crt -inkey ss-localhost-cert.key -out ss-localhost-cert-keystore.p12
keytool -importkeystore -destkeystore salientsoft.p12 -storetype PKCS12 -srckeystore ss-localhost-cert-keystore.p12 -srcstoretype pkcs12 -alias salientsoftdev

4/ Use the Microsoft Management Console to import the above certificate (ss-localhost-cert.crt) into the local computer’s Trusted Root Certification Authorities Store. This post  details how to do this on Windows 10, but Windows 7 was the same.

5/ I used the final keystore for Spring Boot (per details here), and the certificate and key files for node http-server (per details here).

Comments Off on Creating a fully trusted Self Signed localhost certificate