To install Angular Material into a JHipster 7.9.3 app I am following
https://material.angular.io/guide/getting-started and https://cyril-casaucau.medium.com/how-to-add-angular-material-on-an-jhipster-5-x-app-97c9569c9f97
The step
ng add @angular/[email protected]
gives
ng add @angular/[email protected] --force
i Using package manager: npm
√ Package information loaded.
The package @angular/[email protected] will be installed and executed.
Would you like to proceed? Yes
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! While resolving: [email protected]
npm ERR! Found: @angular/[email protected]
npm ERR! node_modules/@angular/core
npm ERR! @angular/core@"14.2.0" from the root project
npm ERR! peer @angular/core@"^14.0.0 || ^15.0.0" from @angular/[email protected]
npm ERR! node_modules/@angular/material
npm ERR! @angular/material@"14.2.0" from the root project
npm ERR!
npm ERR! Could not resolve dependency:
npm ERR! peer @angular/core@"14.3.0" from @angular/[email protected]
npm ERR! node_modules/@angular/animations
npm ERR! @angular/animations@"^14.2.0" from the root project
npm ERR! peer @angular/animations@"^14.0.0 || ^15.0.0" from @angular/[email protected]
npm ERR! node_modules/@angular/material
npm ERR! @angular/material@"14.2.0" from the root project
npm ERR!
npm ERR! Fix the upstream dependency conflict, or retry
npm ERR! this command with --force, or --legacy-peer-deps
npm ERR! to accept an incorrect (and potentially broken) dependency resolution.
npm ERR!
npm ERR! See C:\Users\gregs\AppData\Local\npm-cache\eresolve-report.txt for a full report.
npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\gregs\AppData\Local\npm-cache\_logs\2023-06-30T09_52_14_603Z-debug-0.log
× Packages installation failed, see above.
Is this saying @angular/[email protected] needs peer @angular/core@"14.3.0"?
Whatever, where did @14.3.0 come from? Everything is @14.2.0
npm list --depth=0
gives
+-- @angular-builders/[email protected]
+-- @angular-builders/[email protected]
+-- @angular-devkit/[email protected]
+-- @angular-eslint/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @angular/[email protected]
+-- @fortawesome/[email protected]
+-- @fortawesome/[email protected]
+-- @fortawesome/[email protected]
+-- @ng-bootstrap/[email protected]
+-- @popperjs/[email protected]
+-- @types/[email protected]
+-- @types/[email protected]
+-- @typescript-eslint/[email protected]
+-- @typescript-eslint/[email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
+-- [email protected]
`-- [email protected]
Google and SO have run out of suggestions.
Adding package.json as suggested by Devang Patel
{
"name": "modeldd",
"version": "0.0.1-SNAPSHOT",
"private": true,
"description": "Description for modeldd",
"license": "UNLICENSED",
"scripts": {
"app:start": "./mvnw",
"backend:build-cache": "./mvnw dependency:go-offline",
"backend:debug": "./mvnw -Dspring-boot.run.jvmArguments=\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000\"",
"backend:doc:test": "./mvnw -ntp javadoc:javadoc --batch-mode",
"backend:info": "./mvnw -ntp enforcer:display-info --batch-mode",
"backend:nohttp:test": "./mvnw -ntp checkstyle:check --batch-mode",
"backend:start": "./mvnw -Dskip.installnodenpm -Dskip.npm",
"backend:unit:test": "./mvnw -ntp -Dskip.installnodenpm -Dskip.npm verify --batch-mode -Dlogging.level.ROOT=OFF -Dlogging.level.org.zalando=OFF -Dlogging.level.tech.jhipster=OFF -Dlogging.level.modeldriver.modeldd=OFF -Dlogging.level.org.springframework=OFF -Dlogging.level.org.springframework.web=OFF -Dlogging.level.org.springframework.security=OFF",
"build": "npm run webapp:prod --",
"build-watch": "concurrently 'npm run webapp:build:dev -- --watch' npm:backend:start",
"ci:backend:test": "npm run backend:info && npm run backend:doc:test && npm run backend:nohttp:test && npm run backend:unit:test -- -P$npm_package_config_default_environment",
"ci:e2e:package": "npm run java:$npm_package_config_packaging:$npm_package_config_default_environment -- -Pe2e -Denforcer.skip=true",
"ci:e2e:prepare": "npm run ci:e2e:prepare:docker",
"ci:e2e:prepare:docker": "npm run docker:db:up && npm run docker:others:up && docker ps -a",
"preci:e2e:server:start": "npm run docker:db:await --if-present && npm run docker:others:await --if-present",
"ci:e2e:server:start": "java -jar target/e2e.$npm_package_config_packaging --spring.profiles.active=e2e,$npm_package_config_default_environment -Dlogging.level.ROOT=OFF -Dlogging.level.org.zalando=OFF -Dlogging.level.tech.jhipster=OFF -Dlogging.level.modeldriver.modeldd=OFF -Dlogging.level.org.springframework=OFF -Dlogging.level.org.springframework.web=OFF -Dlogging.level.org.springframework.security=OFF --logging.level.org.springframework.web=ERROR",
"ci:e2e:teardown": "npm run ci:e2e:teardown:docker",
"ci:e2e:teardown:docker": "npm run docker:db:down --if-present && npm run docker:others:down && docker ps -a",
"ci:frontend:build": "npm run webapp:build:$npm_package_config_default_environment",
"ci:frontend:test": "npm run ci:frontend:build && npm test",
"clean-www": "rimraf target/classes/static/app/{src,target/}",
"cleanup": "rimraf target/classes/static/",
"docker:app:up": "docker-compose -f src/main/docker/app.yml up -d",
"docker:db:down": "docker-compose -f src/main/docker/postgresql.yml down -v",
"docker:db:up": "docker-compose -f src/main/docker/postgresql.yml up -d",
"docker:keycloak:await": "echo \"Waiting for keycloak to start\" && wait-on -t 180000 http-get://localhost:9080/realms/jhipster && echo \"keycloak started\" || echo \"keycloak not running, make sure oauth2 server is running\"",
"docker:keycloak:down": "docker-compose -f src/main/docker/keycloak.yml down -v",
"docker:keycloak:up": "docker-compose -f src/main/docker/keycloak.yml up -d",
"docker:others:await": "npm run docker:keycloak:await",
"docker:others:down": "npm run docker:keycloak:down",
"predocker:others:up": "",
"docker:others:up": "npm run docker:keycloak:up",
"java:docker": "./mvnw -ntp verify -DskipTests -Pprod jib:dockerBuild",
"java:docker:arm64": "npm run java:docker -- -Djib-maven-plugin.architecture=arm64",
"java:docker:dev": "npm run java:docker -- -Pdev,webapp",
"java:docker:prod": "npm run java:docker -- -Pprod",
"java:jar": "./mvnw -ntp verify -DskipTests --batch-mode",
"java:jar:dev": "npm run java:jar -- -Pdev,webapp",
"java:jar:prod": "npm run java:jar -- -Pprod",
"java:war": "./mvnw -ntp verify -DskipTests --batch-mode -Pwar",
"java:war:dev": "npm run java:war -- -Pdev,webapp",
"java:war:prod": "npm run java:war -- -Pprod",
"jest": "jest --coverage --logHeapUsage --maxWorkers=2 --config jest.conf.js",
"lint": "eslint . --ext .js,.ts",
"lint:fix": "npm run lint -- --fix",
"prepare": "husky install",
"prettier:check": "prettier --check \"{,src/**/,webpack/,.blueprint/**/}*.{md,json,yml,html,cjs,mjs,js,ts,tsx,css,scss,java}\"",
"prettier:format": "prettier --write \"{,src/**/,webpack/,.blueprint/**/}*.{md,json,yml,html,cjs,mjs,js,ts,tsx,css,scss,java}\"",
"serve": "npm run start --",
"start": "ng serve --hmr",
"start-tls": "npm run webapp:dev-ssl",
"pretest": "npm run lint",
"test": "ng test --coverage --log-heap-usage -w=2",
"test:watch": "npm run test -- --watch",
"watch": "concurrently npm:start npm:backend:start",
"webapp:build": "npm run clean-www && npm run webapp:build:dev",
"webapp:build:dev": "ng build --configuration development",
"webapp:build:prod": "ng build --configuration production",
"webapp:dev": "ng serve",
"webapp:dev-ssl": "ng serve --ssl",
"webapp:dev-verbose": "ng serve --verbose",
"webapp:prod": "npm run clean-www && npm run webapp:build:prod",
"webapp:test": "npm run test --"
},
"config": {
"backend_port": "8080",
"default_environment": "prod",
"packaging": "jar"
},
"dependencies": {
"@angular/animations": "^14.2.0",
"@angular/common": "14.2.0",
"@angular/compiler": "14.2.0",
"@angular/core": "14.2.0",
"@angular/forms": "14.2.0",
"@angular/localize": "14.2.0",
"@angular/platform-browser": "14.2.0",
"@angular/platform-browser-dynamic": "14.2.0",
"@angular/router": "14.2.0",
"@fortawesome/angular-fontawesome": "0.11.1",
"@fortawesome/fontawesome-svg-core": "6.2.0",
"@fortawesome/free-solid-svg-icons": "6.2.0",
"@ng-bootstrap/ng-bootstrap": "13.0.0",
"@popperjs/core": "2.11.6",
"bootstrap": "5.2.0",
"dayjs": "1.11.5",
"minio": "^7.1.1",
"ngx-infinite-scroll": "14.0.0",
"ngx-webstorage": "10.0.1",
"rxjs": "7.5.6",
"tslib": "2.4.0",
"zone.js": "0.11.6"
},
"devDependencies": {
"@angular-builders/custom-webpack": "14.0.1",
"@angular-builders/jest": "14.0.1",
"@angular-devkit/build-angular": "14.2.1",
"@angular-eslint/eslint-plugin": "14.0.3",
"@angular/cli": "14.2.1",
"@angular/compiler-cli": "14.2.0",
"@angular/service-worker": "14.2.0",
"@types/jest": "28.1.8",
"@types/node": "16.11.56",
"@typescript-eslint/eslint-plugin": "5.36.1",
"@typescript-eslint/parser": "5.36.1",
"browser-sync": "2.27.10",
"browser-sync-webpack-plugin": "2.3.0",
"concurrently": "7.3.0",
"copy-webpack-plugin": "11.0.0",
"eslint": "8.23.0",
"eslint-config-prettier": "8.5.0",
"eslint-webpack-plugin": "3.2.0",
"generator-jhipster": "7.9.3",
"husky": "7.0.4",
"jest": "28.1.3",
"jest-date-mock": "1.0.8",
"jest-environment-jsdom": "28.1.3",
"jest-junit": "14.0.1",
"jest-preset-angular": "12.2.2",
"jest-sonar": "0.2.12",
"lint-staged": "13.0.3",
"prettier": "2.7.1",
"prettier-plugin-java": "1.6.2",
"prettier-plugin-packagejson": "2.2.18",
"rimraf": "3.0.2",
"swagger-ui-dist": "4.14.0",
"ts-jest": "28.0.8",
"typescript": "4.8.2",
"wait-on": "6.0.1",
"webpack-bundle-analyzer": "4.6.1",
"webpack-merge": "5.8.0",
"webpack-notifier": "1.15.0"
},
"engines": {
"node": ">=16.17.0"
},
"cacheDirectories": [
"node_modules"
],
"overrides": {
"webpack": "5.74.0"
}
}
My JHipster Mini-Book shows how you can integrate something like Angular Material because JHipster ships with Bootstrap by default.
Modify _bootstrap-variables.scss
and replace it with the contents below.
/*
* Bootstrap overrides https://getbootstrap.com/docs/5.1/customize/sass/
* All values defined in bootstrap source
* https://github.com/twbs/bootstrap/blob/v5.1.3/scss/_variables.scss can be overwritten here
* Make sure not to add !default to values here
*/
// Colors:
// Grayscale and brand colors for use across Bootstrap.
// Customize colors to match Bootstrap Material Theme from https://mdbootstrap.com/docs/standard/
// https://github.com/mdbootstrap/mdb-ui-kit/blob/master/src/scss/bootstrap/_variables.scss
$primary: #009688;
$success: #4caf50;
$info: #03a9f4;
$warning: #ff5722;
$danger: #f44336;
$blue: #0275d8;
// Options:
// Quickly modify global styling by enabling or disabling optional features.
$enable-rounded: true;
$enable-shadows: false;
$enable-gradients: false;
$enable-transitions: true;
$enable-hover-media-query: false;
$enable-grid-classes: true;
$enable-print-styles: true;
// Components:
// Define common padding and border radius sizes and more.
$border-radius: 0.15rem;
$border-radius-lg: 0.125rem;
$border-radius-sm: 0.1rem;
// Body:
// Settings for the `<body>` element.
$body-bg: #fff;
// Typography:
// Font, line-height, and color for body text, headings, and more.
$font-size-base: 0.9rem;
$border-radius: 2px;
$border-radius-sm: 1px;
$font-family-sans-serif: 'Roboto', 'Helvetica', 'Arial', sans-serif;
$headings-font-weight: 300;
$link-color: $primary;
$input-focus-border-color: lighten($blue, 25%);
$input-focus-box-shadow: none;
Then add the following Sass to the bottom of global.scss
.
/* ==========================================================================
custom styles for 21-Points Health
==========================================================================*/
.jh-card {
border: none !important;
}
.jh-navbar {
background-color: #009688 !important;
}
.blockquote {
padding: 0.5rem 1rem;
margin-bottom: 1rem;
font-size: 1rem !important;
font-weight: 100;
border-left: 0.25rem solid #eceeef;
}
a {
font-weight: normal !important;
}
.truncate {
width: 180px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
&.cal-day-notes {
width: 150px;
}
}
.footer {
bottom: 0;
left: 0;
color: #666;
background: #eee;
border-top: 1px solid silver;
position: fixed;
width: 100%;
padding: 10px;
padding-bottom: 0;
text-align: center;
z-index: 3;
font-size: 0.9em;
p {
margin-bottom: 7px;
}
}
.thread-dump-modal-lock {
max-width: 450px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* Override Bootstrap's default vertical-align: top */
.table {
th,
td {
vertical-align: middle !important;
}
}
You can see what this looks like at https://www.21-points.com.
If you’d like to use Material Design for Bootstrap & Angular with JHipster, that’s possible too.
Install The MDB Angular UI KIT:
npm i mdb-angular-ui-kit@3 @angular/cdk@14
Remove all variables from src/main/webapp/content/scss/_bootstrap-variables.scss
.
Comment out the import for Bootstrap in src/main/webapp/content/scss/vendor.scss
:
// Import Bootstrap source files from node_modules
// @import '~bootstrap/scss/bootstrap';
Add the following to import the MDB stylesheet in src/main/webapp/content/scss/vendor.scss:
@import url('https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap');
@import '~mdb-angular-ui-kit/assets/scss/mdb.scss';
Add https://fonts.googleapis.com
and https://fonts.gstatic.com
to the style-src
and font-src
content security policy rules in src/main/resources/config/application.yml
.
jhipster:
...
security:
content-security-policy: "... style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; ... font-src 'self' data: https://fonts.gstatic.com"
Remove the following styles from global.scss
:
/* Error highlight on input fields */
.ng-valid[required],
.ng-valid.required {
border-left: 5px solid green;
}
.ng-invalid:not(form) {
border-left: 5px solid red;
}
Modify the .dropdown-menu
rule to set the display to none.
.dropdown-menu {
padding-left: 0px;
display: none;
}