Archive for 2020

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

March 11th, 2020
12:43 pm
Using self signed SSL with Spring Boot

Posted under Java & Spring & Spring Boot & Web

I needed to use ssl for a Spring Boot backend web service for Yoti, as https is a Yoti requirement.

This post here details how to do this for Spring Boot. The official Oracle docs can also be found here.

The following configuration fragment from the Spring Boot application.properties shows how to configure for ssl using the created keystore (keystore.p12), which was placed in the deployment directory alongside the spring boot jar:-

server.port=8443
server.ssl.key-store-type=PKCS12
server.ssl.key-store=salientsoft.p12
server.ssl.key-store-password=<password>
server.ssl.key-alias=salientsoftdev

Comments Off on Using self signed SSL with Spring Boot

March 11th, 2020
12:34 pm
Using the node http-server over self signed ssl

Posted under Angular & Web

Instructions for setting up http-server for https use may be found here.

To do this I used the same certificate/key combination (but renamed as required) that I created for setting up ssl over WAMP, in my previous post here. As with the WAMP post/installation, the certificate/key were created using openssl, which I downloaded here. The official openssl site may also be found here.

From my previous WAMP installation, I took the certificate.crt/private.key combination from the apache conf folder, and renamed them to cert.pem/key.pem respectively, and placed them in a new ‘keys’ folder conveniently accessible by the batch files that ran all the microapps. I then created ssl versions of all the batch files to run the microapps – an example of the fabric batch file follows:-

cd dist\microapp-fabric-prototype
http-server -p 443 -S -C ..\..\..\keys\ss-localhost-cert.crt -K ..\..\..\keys\ss-localhost-cert.key

https then worked fine and I was able to integrate with the live Yoti for age verification.

Comments Off on Using the node http-server over self signed ssl

March 4th, 2020
6:28 pm
URL Parameter changes when switching to HttpClient

Posted under Angular & Web

From Angular 4.3 onwards, the HttpClient is preferred over the old Http service.

When creating and passing URL parameters, the new HttpParams object must be used.

Details and examples of this are shown here.

Note carefully as per the post that when passing parameters to the http methods e.g. get, the json property name is now ‘params’ instead of ‘search’, and the append method should be called to add parameters (although the last poster indicates that calling set worked for him as well).

Another gotcha is that the HttpParams object is also immutable, so that every time you add a parameter a new object is created/returned and you must use the returned object, e.g. in fluent style when adding multiple parameters, otherwise you will end up using your empty initial HttpParams object.

Comments Off on URL Parameter changes when switching to HttpClient

March 3rd, 2020
2:13 pm
combineLatest changes when upgrading to rxjs 6

Posted under Angular & RxJS & Web

Note that you must now call this as a function rather than a method of another observable, see here.

Also note that as before you can use a projection function to map the results, as an alternative to using .pipe(map…)). If you are using the projection function, you should not use the spread syntax with the projection as the last argument as this is deprecated. Rather pass the observables as an array, followed by the projection function. More details on the project are here, and in the code examples here.

 

Comments Off on combineLatest changes when upgrading to rxjs 6