Archive for 2020

March 3rd, 2020
11:43 am
Angular build fails with “Progress Plugin Invalid Options”

Posted under Angular & Web & Webpack

When upgrading an angular 4 project (places-admin) to angular 6, I got the above error when building.

The problem and solution are detailed here.

The issue appears to be caused by webpack 4.25.* breaking compatibility with the plugin.

Applying the fix in the above post solved the problem, by adding

“webpack”: “4.24.0”

to the devDependencies section in package.json

 

Comments Off on Angular build fails with “Progress Plugin Invalid Options”

February 20th, 2020
4:34 pm
Loading/Busy Indicator

Posted under Angular & PrimeNG & Web
Tags

I needed an indicator such as some kind of spinner whilst microapps were loading.

PrimeNG has a progress spinner here. However, the implementation uses scalable vector graphics, which I was not able to use.

My base line for browser support included IE11, and unfortunately this only has a partial implementation which broke when using the PrimeNG spinner.

I therefore used loading.io to design my own animated gif. The site has a number of free as well as paid for spinner/busy patterns, and each one has a form allowing a number of variables to be tweaked, allowing customisation of your spinner design. You can then download the result in a choice of formats including animated GIF as well as SVG. I stuck with an animated GIF as this worked across all the browsers. I designed different versions (e.g. colour), making them themeable as part of the application theme. For each base theme I implemented a choice of 2 spinners – A rolling spinner, and a spinning circles spinner. Both gave excellent results and were free.

 

Comments Off on Loading/Busy Indicator

February 20th, 2020
4:19 pm
Deep merging of JS objects

Posted under Angular & Web

I needed to do this to implement a configuration profile/configuration override pattern, whereby a configuration profile contained json configuration which would selectively override some configuration options by merging the profile into the overall configuration.

This post here discusses deep merging of objects, and gives examples such as this one, which I used as the basis of my implementation. I did not need or want to get into deep merging of arrays, which other answers discussed, and I did not want to involve lodash.

 

Comments Off on Deep merging of JS objects

February 20th, 2020
3:15 pm
Using the Angular APP_INITIALIZER

Posted under Angular & Web

This allows the use of asynchronous operations (such as configuration loading) at Angular bootstrap time. It is documented (somewhat minimally to say the least) here.

In my case I needed it to allow early script loading of (in my case Yoti) external scripts at bootstrap time. A Yoti script overwrote some promise code that had already been patched by zone.js earlier. Subsequently, zone.js detected this and the application failed. This is documented here. I also used it to load the app configuration dynamically, rather than from index.html. As well as being a better design due to decoupling from index.html and opening the door to pulling the configuration from an external provider, this also allowed multiple configuration sets to be selectable e.g. from a query string parameter in the url.

This Stack Overflow post shows how to implement the APP_INITIALIZER.  This tutorial post does the same, and goes into details about using multiple providers via a multi provider token. Basically you need to pass a function or a lambda which returns a promise, which completes when your asynchronous operation is done. One point worthy of note is that when rejecting a promise, you need to pass something in the reject, or Angular throws an error stating Cannot read property ‘ngOriginalError’ of undefined.

My implementation is here:

@NgModule({
declarations: [
AppComponent,
FabricComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,

],
schemas: [CUSTOM_ELEMENTS_SCHEMA],
providers: [
…,
ConfigurationService,
ConfigurationValidator,
ScriptLoader,
PreBootScriptLoader,
ObjectUtils,
{
provide: APP_INITIALIZER,
useFactory: (configurationService: ConfigurationService, preBootScriptLoader: PreBootScriptLoader) => () => {
  return configurationService.load().then(() => preBootScriptLoader.load);
},
deps: [ConfigurationService, ConfigurationValidator, PreBootScriptLoader, ScriptLoader, ObjectUtils],
multi: true
},
],
bootstrap: [AppComponent]
})

Promise rejection code fragment showing passing an error in the reject:

if (this.configurationValidator.validate(appConfig)) {
  console.error(‘Configuration failed validation’, appConfig);
  reject(new Error(‘Configuration failed validation as above.’));
} else {
  resolve();
}

Comments Off on Using the Angular APP_INITIALIZER

February 6th, 2020
10:27 pm
Zone.js gives errors if Promise code is patched via external js after zone is loaded

Posted under Angular & Web

When integrating a microapp which uses the Yoti identity platform for age verification, I hit issues where other microapps would fail to load after the Yoti/age verification microapp had loaded.

The following error appeared on the browser console:-

Error: Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.
Most likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)
at Function.push../node_modules/zone.js/dist/zone.js.Zone.assertZonePatched (polyfills.js:6911)
at new NgZone (vendor.js:42512)
at getNgZone (vendor.js:43220)
at PlatformRef.push../node_modules/@angular/core/fesm5/core.js.PlatformRef.bootstrapModuleFactory (vendor.js:43116)
at vendor.js:43162
at www.yoti.com/:1

A similar instance of this issue, where Bing loads after zone.js and similarly patches promise code, is detailed here.

In my case the culprit was the Yoti client SDK, which did the patching/overwriting. A temporary fix, which worked successfully, was to load the Yoti SDK in index.html, prior to the angular bootstrap process, and remove/disable my existing code which loaded the SDK dynamically via a script tag (after zone had loaded).

My final solution was to use an Angular app initializer token, which permits a custom initialise function to be created. This can perform  an asynchronous operation to be performed which returns a promise to the app initialiser, which allows bootstrapping to continue only when the promise has succeeded.

The details of this implementation are in a separate post, here.

Comments Off on Zone.js gives errors if Promise code is patched via external js after zone is loaded

February 6th, 2020
7:43 pm
Remote loading of Angular Elements from separate webpack bundle causes unwanted multiple bootstraps

Posted under Angular & Web

I have used this pattern here from Manfred Steyer (a Google Developer Expert who has been involved in coding the Angular 8 Ivy release), to allow remote loading of separately developed and packaged Angular Elements, each of which is build like a separate app.

Whilst the application was able to successfully load and display a number of angular elements as separate microapps, the bootstrapping process had issues, manifested with console errors stating ‘zone.js already loaded’.

This post here discusses this kind of issue. Whilst I did not experience the same failure as detailed in the post, it was a related issue.

It has also been raised as an angular issue here.

Rob Wormald’s comment of 14/5/18, after he looked into it, indicated that renaming the global webpackJsonp objects to something unique in each bundle would solve the problem, but was not a recommended solution. From the discussion in the post comments, it looks like Angular 8 and 9 have a better solution to this issue.

I am not yet able to upgrade Angular from the 6.1.7 I am currently using to 8 or 9. PrimeNG has compatibility with the latest Angular version, and also switching to a much later PrimeNG would cause me theming issues as Prime have dropped the legacy theming for a newer, paid for, non open source theme creator, which raises further issues.

As my current work is a POC, I therefore took a pragmatic approach and implemented Rob Wormald’s idea as above. One of the posters in the thread above took this approach using a custom webpack solution as detailed here. I took a similar approach but avoided the custom webpack solution by using a simple NPM post build script, written in javascript, run with Node, which runs after the webpack bundle has been created. The script uses the replace plugin to rename the objects in the files. One reason was that I wanted to be decoupled from any direct webpack customisation via a webpack build plugin as from the comments there can be issues getting this to work depending on the actual Angular version in use. I have seen comments that the angular development team are keen to encapsulate/hide the internals of webpack building to allow them the complete ability to control and change it. In fact this has happened with later angular versions.

Whilst any such solution will be temporary and will need to be swapped out when eventually moving to Angular 9 or later, this solution completely solved the problem, and zone.js was no longer loaded multiple times.

The solution involved the following steps:-

1) Add a postbuild step in package.json, to run the post build script:-

“scripts”: {
“ng”: “ng”,
“start”: “ng serve”,
“prebuild”: “cd src/assets/resources/themes/salient && node-sass theme.scss theme.css –source-map .”,
“build”: “ng build”,
“postbuild”: “node post-build.js”,

The postbuild step is automatically run when you use “npm run build” to do a build. This step edits the built bundle to do the required renaming.

Note also that in the above example I also have a prebuild step, which is used to build SCSS themes which are deployed as static assets outside the bundle, to allow dynamic theme selection. The prebuild step also runs automatically when “npm run build” is done.

2) The post build script uses the npm replace package. Note that using the replace from javascript rather than a CLI command avoids the collision with the standard Windows replace, and also allows a tidier way of handling the various components of the Webpack script bundle.  An example of the code follows. Note that as node uses the V8 javascript engine, array maps and lambdas “=>” are available to use:-

var replace = require(“replace”);

/* arguments: Object suffix, project folder name (dist subfolder),
*            list of all the generated webpack scripts to be updated */
doWebpackReplace(‘MicroappFabric’,’microapp-fabric-prototype’,
[‘main.js’, ‘polyfills.js’, ‘runtime.js’, ‘styles.js’, ‘vendor.js’]);

function doWebpackReplace(name, filename, paths) {
   replace({
      regex: ‘\\[“webpackJsonp”\\]’,
      replacement: `[“webpackJsonp${name}”]`,
      paths: paths.map((p) => `dist\\${filename}\\${p}`),
      recursive: false,
      silent: false,
   });
}

3) Make sure the npm file replace package is installed via “npm install –g replace”, and make sure it is listed in the “dependencies” section of package.json:-

“primeng”: “6.1.3”,
“replace”: “^1.1.5”,
“rxjs”: “6.3.2”,

Comments Off on Remote loading of Angular Elements from separate webpack bundle causes unwanted multiple bootstraps

January 24th, 2020
5:32 pm
Spring Boot no longer returns HTTP reason phrase in responses

Posted under Java & Spring & Spring Boot & Tomcat

I noticed this when a web service returned a blank reason phrase, which tripped up Angular due to an Angular issue which I have documented here.

It appears to be a Spring Boot Tomcat version change issue – a later Tomcat ignores the reason phrase and does not return it, as detailed here.

As reason phrases are being deprecated anyway, and I don’t use them, I have just ignored the issue, but it is worth being aware of it when debugging.

Comments Off on Spring Boot no longer returns HTTP reason phrase in responses

January 24th, 2020
5:26 pm
Angular HttpErrorResponse statusText set to OK even if error

Posted under Angular & Web

I noticed the above whilst debugging in Chrome, when a web service returned a 401 status, the statusText as above was still OK.

This appears to be an angular issue as detailed here and here.

The latter post above indicates that it originally was an XHR spec requirement, but per the post the XHR spec has subsequently changed so the issue was requested to be reopened.

As I don’t use the statusText anyway I am ignoring the issue.

It was triggered by a related Spring Boot issue which I have documented here.

Comments Off on Angular HttpErrorResponse statusText set to OK even if error

January 22nd, 2020
4:11 pm
PrimeNG theming no longer open source

Posted under Angular & PrimeNG & Web

The PrimeNG changelog states that as of 8.0.0-rc1, the old theming architecture based on Themeroller is being removed completely in favour of the new theme architecture and designer, as per change #7762.

The new theme architecture looks much more fully functional, and the designer looks a good and powerful tool.

A number of themes are paid for and not open source, as before which is fine and not a problem.

The designer itself is also paid for, which is perhaps slightly sad but not a real problem if you can roll your own themes directly in SCSS, e.g. by adapting a free theme as I have done in the past.

 

However, the big frustration is that the full SCSS theming API definition itself is proprietary and not open sourced/publicly documented, as per this prime post here. This means that the only official way to create a new SCSS based theme is with the designer, which is paid for.

This is a real frustration as due to the version matrix, if you stick with an older PrimeNG you cannot upgrade to the latest Angular, e.g. to Angular 8/Ivy.

One way around it is detailed in this helpful blog post here, which involves a certain amount of reverse engineering of the free themes. This is in itself not a big issue as normally in the past I have created themes by modifying an existing themeroller theme (or, for Primefaces, even by rolling one via the ThemeRoller web site tool).

However as the post points out, the fact that the global common SCSS is not now released, we may be subject to breaking changes in the future.

Prime states on the PrimeNG page that the components are all open source, but with parts of the theming architecture now being proprietary and not released, this is does not now appear to be the case any more.

I will continue to monitor this and see what others are doing, but it may be that for my own projects, for the first time ever I will need to move to another component set (e.g. use Material Design when using Angular) and no longer use Prime.

Comments Off on PrimeNG theming no longer open source

January 21st, 2020
3:50 pm
Using flex for PrimeNG message layout vs float/display:table-cell

Posted under Angular & PrimeNG & Web

I’m currently using PrimeNg 6.1.3 with the older themeroller architecture

This has a glitch on message display as follows:

I wanted the text to be indented past the LHS icon rather than on a new line.

My old school version in my theme used a left float on the icon, and a display:table-cell on the <ul> text container.

This worked fine as follows:-

I didn’t like using display:table-cell but had to in this case as I had no control over the markup generated by the message component, only the theme SCSS.

My second version, which is simpler, just removed the float and the display:table-cell, and made the containing div a flex container via display:flex.

This worked in exactly the same way, and was all I needed to do. The flex defaults just worked with no strange tweaking required.

The W3 Schools page on flex, including numerous try out examples that you can play with, is here.

PrimeNG Generated Markup

<div class=”ui-messages ui-widget ui-corner-all ng-tns-c2-0 ng-trigger ng-trigger-messageAnimation ng-star-inserted ui-messages-warn” style=”display: block; transform: translateY(0px); opacity: 1;” ng-reflect-ng-class=”[object Object]”>
   <a class=”ui-messages-close ng-tns-c2-0 ng-star-inserted” href=”#” style=””>
      <i class=”pi pi-times”></i>
   </a>
   <span class=”ui-messages-icon pi pi-exclamation-triangle” ng-reflect-klass=”ui-messages-icon pi” ng-reflect-ng-class=”pi-exclamation-triangle”></span>
   <ul class=”ng-tns-c2-0″>
      <li class=”ng-tns-c2-0 ng-star-inserted” style=””>
         <span class=”ui-messages-summary ng-tns-c2-0 ng-star-inserted”>Age Invalid:</span>
         <span class=”ui-messages-detail ng-tns-c2-0 ng-star-inserted”>Your age is  outside the required age range of 18 to 50</span>
      </li>
   </ul>
</div>

Original Style Fragment (SCSS)

.ui-messages.ui-widget {
padding: .5em;
border: 0 none;
color: $contentTextColor;

.ui-messages-icon {
      float: left;
margin-right: .1em;
}
&, .ui-messages-close {
color: $headerIconTextColor;
~ ul {
padding-right: 1.4em;
}
.pi, .ui-messages-icon.pi {
font-size: 1.6em;
}
}
    ul {
display:table-cell;
}

.ui-messages-summary {
margin-left: 0;
}
&.ui-messages-success {
background-color: #b7d8b7;
}
/*…other message severities… */
}

Flex Style Fragment (SCSS)

.ui-messages.ui-widget {
  /* We have to use !important here as the markup (which we cannot control)
uses an inline style for display:block 🙁 */
display: flex !important;
    padding: .5em;
border: 0 none;
color: $contentTextColor;

.ui-messages-icon {
margin-right: .1em;
}
&, .ui-messages-close {
color: $headerIconTextColor;
~ ul {
padding-right: 1.4em;
}
.pi, .ui-messages-icon.pi {
font-size: 1.6em;
}
}
.ui-messages-summary {
margin-left: 0;
}
&.ui-messages-success {
background-color: #b7d8b7;
}
/*…other message severities… */
}

Comments Off on Using flex for PrimeNG message layout vs float/display:table-cell