Archive for the 'Uncategorized' Category

March 22nd, 2024
5:23 pm
React Framework

Posted under Next.js & React & Uncategorized & Web

Initial points found upon trying out React…

  1. Deploying and running a Basic React App

The React framework site and nearly all the other tutorial sites I found do not make it clear at all how to deploy/run one of the react examples to a static web server, much like Angular does by default, with the front end framework bootstrapped from index.html. In most cases, they suggest using Node.js on the server to run the app, which then creates everything dynamically and just lets you access the site e.g. via localhost:3000 if running locally.

Whilst this may be efficient if you have node.js on your server, it does not help when deploying to a static web server as I would be e.g. with Zen internet, or when extending an existing web app with some react on one of the pages.

After quite a bit of head scratching, I found this simple post which showed how to simply add the “homepage”: “.” directive to package.json, which defines the homepage for the app. This is picked up by the webpack build, and an index.html is created (or extended) with the necessary javascript to start react. I tested this out by amending this simple react calculator tutorial app.  It built correctly by adding the necessary webpack bootstrap code to the public index.html template in the app, and it ran fine both locally with http-server and on zen internet. It also ran correctly locally via npm start, which runs it dynamically under node where this is available on the server.

In my case I had deprecated OpenSSL build issues as detailed on this post here. I worked around these purely just to get the example to build and run as it was my very first stab at running react, by using set NODE_OPTIONS=--openssl-legacy-provider as per the post. Note that this is a dangerous legacy setting which should not normally be used as it opens up legacy SSL vulnerabilities. For my simple initial test this was not a concern however.

  1. Creating and building a React App from scratch

I used create-react-app for this which looked like a really simple tool to create a standard build simply, somewhat like the angular CLI. This post here shows how to do this with typescript enabled by default, by simply using the following npx command:

npx create-react-app my-app --template typescript

This created a simple app which again I could modify to be served from a static server as above via the homepage directive. However, On researching this further, I noted that create-react-app is now deprecated.

I am continuing to use this for basic react learning, but going further forward, I will likely be adopting Next.js as the framework to use with react and to build apps with. The react site says that one of the recommended additional frameworks should now be used and Next.js seemed best for me initially, as it works with static sites and as a wikipedia presence. Remix among others is popular but did not have a wikipedia page, and I liked the static site emphasis of Next.js. However as I wanted to learn one step at a time and not hit 2 frameworks in one go, I intend to continue with create-react-app for the basics at first.

 

 

 

 

Comments Off on React Framework

August 5th, 2022
3:36 pm
PrimeNG V13 Picklist Component does not scroll on touch device when drag drop enabled

Posted under Angular & PrimeNG & Uncategorized
Tags , ,

In V6 or PrimeNG, you could enable drag drop reordering on the picklist and still scroll on a touch device, e.g. on a mobile phone. This was handled nicely by using a click and hold to select an item for drag drop, and a swipe to do scrolling.

In V13 this is now broken – touching on an item instantly selects it for dragging, without using the previous click and hold, so that it is not possible to scroll by swiping the source or target list any more. I have confirmed that it used to work on my old V6 microapps version which used a standard PrimeNG V6.1.3 picklist, and also have checked the current PrimeNG showcase online – the current showcase is broken in exactly the same way when trying to scroll via touch on mobile. Whilst scroll bars are present on the RHS of the list, they are very small for Mobile. I did try to enlarge the scroll bars for mobile, using some webkit specific styling, but this proved problematic as it is not fully supported for Firefox – they cannot be resized on firefox. Even when I did get it working, selecting the scroll thumbtrack for mobile proved intermittent and tricky – not a nice interaction at all.

My simple workaround for this is to disabled dragdrop for the picklist for a touch device by setting dragdrop=false (i.e. dragdrop=!touchDevice). I already have a config property in the fabric to detect a touch device, and have replicated that as a global config parameter which is visible to all the microapps. The picklist can then use this. This is actually better than it sounds – whilst you cannot reorder items within a list any more, you can move between source and target using the buttons, and drag/drop is tricky on a mobile anyway as the source and target lists appear one above the other with typically only one of them visible so dragging between them is tricky as again scrolling is involved.

For reference, changing the scrollbar styling via the webkit styles is documented here and here.

Applying the webkit styles is very picky per the posts above – spacing etc. matters – there must not be a space between the element/class name and for example ::-webkit-scrollbar or it won’t work. In the end this SCSS styling worked for me, and fortunately I was able to get it working with a classname rather than just e.g. a ul element which is the one I wanted to hit:

.p-component.p-picklist {
.p-picklist-header {
background: $ss-widget-header;
color: $ss-widget-header-text;
}

.p-picklist-list {
&::-webkit-scrollbar {
width: 50px;
height: 50px;
}
&::-webkit-scrollbar-thumb {
width: 50px;
height: 50px;
background: #a8a8a8;
border-radius: 4px;
}

As above I dumped this approach anyway, as even with a very large scrollbar and thumb track, it was difficult to consistently scroll on mobile, and anyway  the source and target for drag/drop were not both in view simultaneously anyway.

 

Comments Off on PrimeNG V13 Picklist Component does not scroll on touch device when drag drop enabled

August 4th, 2022
2:38 pm
Caching of old microapp scripts breaks new version

Posted under Angular & Uncategorized & Webpack
Tags , ,

An old chestnut this – when upgrading from an old version on my hosted environment, my chrome based dev desktop worked fine, mainly due to my habit of hitting ctrl/f5 which clears the cache before loading.

However, on my android mobile, this needs an explicit cache clear before loading the page e.g. via the settings/history etc., which I was not in the habit of doing. Therefore when testing the new version on mobile, it failed. The new version was a production build which did not have source maps. The old version was a dev one with source maps. The console errors indicated an inability to find and load the source maps, which were not present in the latest prod deployment, but were still being requested by the cached scripts on the mobile. An explicit cache clear solved the problem. 

When I tried this again on the desktop without the cache clear, i.e. with a straight refresh, I was able to duplicate the error seen on the android chrome.

Note that the problem only applies to the fabric deployment as all the others have a timestamp (ts=) querystring parameter added to the scripts when loading, which prevents caching. I normally disable the output hashing on all microapps including the fabric for convenience, to avoid editing the app config to change the names of all the dynamically loaded scripts, even for a prod build.

Doing this on the Fabric is unnecessary as the scripts are not loaded dynamically by my code, so if I left the hashing on for the fabric, this would solve the problem, as the timestamp querystring would sort the issue for all the others.

Going forward, I intend to improve automation of the build process for hosted deployments by providing e.g. an NPM script to build all the microapps into a single zipped deployment which can be just uploaded and unzipped – at present I am having to do each one individually and copy up the dist directory. Whilst all this is only a POC application, I am doing it often enough to make this worthwhile so as not to waste time or make mistakes with it.

Doing this would also allow the possibility of using my own timestamps on all the filenames for every script, and dynamically modifying the config to incorporate the timestamps in the build script. This would allow caching to be left enabled for the code scripts (but not for the config), which would actually be a benefit as it would improve startup times and lessen bandwidth usage – especially relevant for mobiles. I could add a fabric config parameter to indicate whether the querystring timestamps should be added or not when loading scripts, so that the feature can still be used when needed. Perhaps I could leave this enabled for dev mode and not bother with timestamps on the actual filenames for example.

Using my own timestamps on the names would simplify and standardise the names, as I could use an identical timestamp on all scripts for every microapp done as part of a given build, to simplify naming and build automation – I would only need to pass around one single timestamp parameter which would be used for all generated script files and in the config.

 

Comments Off on Caching of old microapp scripts breaks new version

February 25th, 2021
12:23 pm
Angular 11 – remote loading of Angular Element from separately deployed webpack bundle

Posted under Angular & Uncategorized & Web & Webpack

This follows on from my original post here for Angular 6.

In Angular 11, the up-and-coming approach to this is to use Module Federation for remote loading of microapps/micro-frontends. Manfred Steyer has a new article series on this whole approach here, and the second article about using Angular for this may be found here.

My issue with module federation at present is that it is still appears too nascent to simply ‘just work as standard’ with angular – the above posts need a number of workarounds including the use of yarn, and I was unwilling to switch to this method just for my present requirement which is just the generation of simple proof of concept work.

At present, I am therefore continuing to use my original approach as above for my POC work, as it still works with Angular 11. I have tweaked the approach a little to allow performing production builds, by disabling the hashes added to the filenames (I already use my own alternative method for cache busting/cache avoidance using a query string parameter). Details are shown below.

package.json scripts section

{
"name": "microapp-fabric-prototype",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"prebuild": "npm run scss",
"build": "ng build",
"postbuild": "node post-build.js",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"scss": "npm run scss1",
"scss1": "cd src/assets/resources/themes/salient-v11-violet && sass theme.scss:theme.css --source-map .",
"prebuildProd": "npm run scss",
"buildProd": "ng build --prod --output-hashing none",
"postbuildProd": "node post-build-prod.js"
},

post-build.js

/* Do post build actions on the webpack bundle.
* Rename the webpack jsonp objects throughout, to prevent invalid multiple bootstraps due to name collisions
* This is due to an angular bug - see here: https://github.com/angular/angular/issues/23732
* This script requires the npm replace package: https://www.npmjs.com/package/replace
* To install use: "npm install replace -g" */

var replace = require("replace");

doWebpackReplace('MicroappFabric','microapp-fabric-prototype',
['main.js', 'polyfills.js', 'runtime.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,
});
}

post-build-prod.js

/* Do post production build actions on the webpack bundle.
* Rename the webpack jsonp objects throughout, to prevent invalid multiple bootstraps due to name collisions
* This is due to an angular bug - see here: https://github.com/angular/angular/issues/23732
* This script requires the npm replace package: https://www.npmjs.com/package/replace
* To install use: "npm install replace -g" */

var replace = require("replace");

doWebpackReplace('MicroappFabric','microapp-fabric-prototype',
['main.js', 'polyfills.js', 'runtime.js']);

function doWebpackReplace(name, filename, paths) {
replace({
regex: 'window\\.webpackJsonp',
replacement: `window.webpackJsonp${name}`,
paths: paths.map((p) => `dist\\${filename}\\${p}`),
recursive: false,
silent: false,
});
}

At present, I will continue to monitor the situation with Module Federation, and will likely switch to using it when it really is working ‘out of the box’ with no tweaks or complications.

 

Comments Off on Angular 11 – remote loading of Angular Element from separately deployed webpack bundle

February 19th, 2021
6:05 pm
PrimeNG 11/Angular 11 build fails due to missing @angular/cdk dependency

Posted under Angular & PrimeNG & Uncategorized & Web
Tags , ,

… as above – I received the following error in relation to a PrimeNG p-dropdown used with a p-dataview:

Error: The target entry-point “primeng/dataview” has missing dependencies:
– @angular/cdk/scrolling

This issue is covered here.
I haven’t seen this before, but installing @angular/cdk resolved the build failure. This appears to be a transitive dependency issue which should have been resolved by my dependencies on PrimeNG.

 

Comments Off on PrimeNG 11/Angular 11 build fails due to missing @angular/cdk dependency

February 10th, 2021
6:54 pm
Pinning a title bar on a page with Angular 11/PrimeNG 11

Posted under Angular & PrimeNG & Uncategorized & Web
Tags ,

My initial attempt on this was to use static positioning when the title bar was unpinned (e.g. scrollable), and fixed positioning when the bar was pinned.

When using fixed positioning as above, the title bar is no longer in the normal flow so the rest of the content (in my case, encapsulated in a main container div) will sit underneath the title bar. I therefore used a top margin when pinned to prevent the top of the content being hidden. Some issues arose with this as follows:

1/ It was necessary therefore to add an additional margin to the main container to avoid occluding the content under the title bar, which meant exactly knowing its height. In addition, to allow a gap between the title bar and the content when pinned, I added a border to the title bar of the same colour as the page background, in effect to act as a kind of margin. This worked fine.

1/ My title bar was floated, so it automatically resized to fit its content. this meant that the margin allowance on the main content div would have to vary dynamically on resize.

2/ One way around this was to set media query breakpoints to trigger on the resize, and to set a fixed height for the title bar rather than floating it, and setting the margin on the content to match in each media query. In addition to this, I implemented a flexbox solution where the container was sized and the content centered within it. I was not so keen on this as it lost the ability to dynamically resize the title bar container as needed by the content resizing, and might cause problems if the layout/text changed in the title bar for example.

3/ Another way was to use a resize event and change the size of the margin on the content programmatically, using an rxjs debounced resize event. This worked pretty well, but I needed to switch the content margin on and off when the title bar was pinned/unpinned. This should have worked ok, but I noticed some slight visual movements in some page elements on pinning change, even though I could not see any style or layout changes in the browser inspector. This was annoying.

4/ I then tried using absolute positioning of the title bar when unpinned, and fixed positioning when pinned. This relied on using the same programmatic margin on the content for both, and in fact simplified the code, as I did not have to switch off the programmatic margin change when unpinning the title bar – it was used all the time, as absolute positioning was also outside the normal flow. Also, the slight glitches I saw on the page were completely eliminated.

I therefore stuck with method 4/ as the final solution. Some sample code showing the programmatic resize is as follows:-

private readonly resizeDebounceTime = 100;
private resizeObservable!: Observable<Event>;
private resizeSubscription!: Subscription;
private readonly formatPixelSize = (pixels: number) => `${pixels}px`;

ngAfterViewInit(): void {
   this.initBannerSpacingAdjustment();
}

ngOnDestroy(): void {
   this.destroyBannerSpacingAdjustment();
}

private initBannerSpacingAdjustment(): void {
   this.adjustBannerSpacing();
   this.resizeObservable = fromEvent(window, 
      ‘resize’).pipe(debounceTime(this.resizeDebounceTime));
   this.resizeSubscription = this.resizeObservable.subscribe(event => 
      this.adjustBannerSpacing());
}

private destroyBannerSpacingAdjustment(): void {
   if (this.resizeSubscription) {
      this.resizeSubscription.unsubscribe();
}
}

private adjustBannerSpacing(): void {
   /* note that the offsetHeight is the total height of the banner,
    * including padding and border */
   this.mainContainer.nativeElement.style.marginTop =
      this.formatPixelSize(this.banner.nativeElement.offsetHeight);
}

 

Comments Off on Pinning a title bar on a page with Angular 11/PrimeNG 11

February 8th, 2021
6:04 pm
Using Font Awesome with Angular 11/PrimeNG 11

Posted under Angular & PrimeNG & Uncategorized & Web
Tags ,

Update 4/3/21

I had problems again when trying to display font-awesome icons in a microapp/web component. In this case, my parent fabric application which loaded the web component had font awesome loaded in package.json but not in angular.json. I removed font-awesome from the web component application in both package.json and angular.json as the parent had loaded it in both places. This then worked correctly. There may be a similar issue with e.g. the prime icons etc. but have not researched this. Clearly PrimeNG itself is needed in both applications as the child web component has development dependencies on it. My theme styling however is only loaded in the parent fabric, and it makes sense that font-awesome behaves the same way.

Original Post

My previous post about using font awesome with Angular  up to v6 and PrimeNG up to v6 is here

With PrimeNG 11, Prime have introduced their own icon set, PrimeIcons.

I wanted to use some font awesome icons as well as they have a larger set, but initially they would not display. When trying again later it all worked fine, and am unsure what I got wrong the first time around. To be clear, the following steps were needed:

1/ Install font awesome and add to package.json (–save adds to package.json)

npm install font-awesome –save

2/ Add a style reference to angular.json

“styles”: [
“node_modules/primeng/resources/primeng.min.css”,
“node_modules/font-awesome/css/font-awesome.min.css”,
“node_modules/primeicons/primeicons.css”,
“src/messages.scss”,
“src/styles.scss”
],

Double check that the referenced css file actually exists under node-modules for the version in use. in my case, this was 4.7.0.

I was looking for pin/unpin icons for a banner bar, and could only find a vertical pin, fa-thumb-tack – I also wanted a horizontal pin to designate the unpinned state. Fortunately, font awesome has the ability to transform icons e.g. to rotate them. This is more limited in v4, but rotation is allowed, so my reference was as follows:

<p-toggleButton [(ngModel)]="bannerPinned" onIcon="fa fa-thumb-tack" offIcon="fa fa-thumb-tack fa-rotate-90"
class="ss-pin-banner"></p-toggleButton>

This worked perfectly. v5, which was not available directly to install via npm at the time, allows more transformations. The transforms are detailed in this stack overflow post and this font awesome page.

 

 

Comments Off on Using Font Awesome with Angular 11/PrimeNG 11

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