I want to integrate Here Maps for Javascript in PowerApps Code Component which is written in typescript.
I am getting __webpack_require__is not defined error. Because PCF have their own webpack, I added a webpack script and add “bundle”: “webpack” to my package.json.
I am lost at what I should be doing to fix this.
index.ts
import { IInputs, IOutputs } from "./generated/ManifestTypes";
import "@here/maps-api-for-javascript";
export class heremaps
implements ComponentFramework.StandardControl<IInputs, IOutputs>
{
private _container: HTMLDivElement;
private _map: H.Map | null = null;
// Hardcoded API key
private readonly API_KEY: string =
"api_key";
constructor() {}
/**
* @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to property names defined in the manifest, as well as utility functions.
* @param notifyOutputChanged A callback method to alert the framework that the control has new outputs ready to be retrieved asynchronously.
* @param state A piece of data that persists in one session for a single user. Can be set at any point in a controls life cycle by calling 'setControlState' in the Mode interface.
* @param container If a control is marked control-type='standard', it will receive an empty div element within which it can render its content.
*/
public init(
context: ComponentFramework.Context<IInputs>,
notifyOutputChanged: () => void,
state: ComponentFramework.Dictionary,
container: HTMLDivElement
): void {
// Create or reuse the container for the map
if (!this._container) {
this._container = document.createElement("div");
this._container.id = "map";
this._container.style.width = "100%";
this._container.style.height = "100%";
container.appendChild(this._container);
} else {
// Clear the container's content to avoid reusing the same element
this._container.innerHTML = "";
}
// Dispose of any existing map instance to prevent "already in use" errors
if (this._map) {
this._map.dispose();
this._map = null;
}
// Initialize the map
this.initializeMap();
}
private initializeMap(): void {
// Initialize communication with the platform
const platform = new H.service.Platform({
apikey: this.API_KEY,
});
// Create the map instance
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const defaultLayers: any = platform.createDefaultLayers();
this._map = new H.Map(this._container, defaultLayers.vector.normal.map, {
center: { lat: 52, lng: 5 },
zoom: 5,
pixelRatio: 2,
});
// Add a resize listener to ensure the map occupies the whole container
window.addEventListener("resize", () => this._map?.getViewPort().resize());
// Make the map interactive
const behavior = new H.mapevents.Behavior(
new H.mapevents.MapEvents(this._map)
);
const ui = H.ui.UI.createDefault(this._map, defaultLayers);
// Add the polyline
this.addPolylineToMap();
}
private addPolylineToMap(): void {
const lineString = new H.geo.LineString();
lineString.pushPoint({ lat: 53.3477, lng: -6.2597 }); // Dublin
lineString.pushPoint({ lat: 51.5008, lng: -0.1224 }); // London
lineString.pushPoint({ lat: 48.8567, lng: 2.3508 }); // Paris
lineString.pushPoint({ lat: 52.5166, lng: 13.3833 }); // Berlin
this._map?.addObject(new H.map.Polyline(lineString));
}
public updateView(context: ComponentFramework.Context<IInputs>): void {
// Handle updates if needed, but avoid re-initializing the map
}
public getOutputs(): IOutputs {
return {};
}
public destroy(): void {
// Cleanup map instance
if (this._map) {
this._map.dispose();
this._map = null;
}
}
}
webpack.config.js
import { resolve as _resolve } from "path";
import { fileURLToPath } from "url";
import { dirname } from "path";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
export const entry = "./index.ts";
export const module = {
rules: [
{
test: /.tsx?$/,
use: "ts-loader",
exclude: /node_modules/,
},
],
};
export const resolve = {
extensions: [".tsx", ".ts", ".js"],
};
export const output = {
filename: "index.ts",
path: _resolve(__dirname, "dist"),
};
export const mode = "production";
export const node = {
global: false,
};
export const performance = {
maxEntrypointSize: 2048000,
maxAssetSize: 2048000,
};
pcfconfig.json
{
"outDir": "./out/controls",
"build": {
"production": {
"webpack": "./webpack.config.js"
}
}
}
package.json
{
"name": "pcf-project",
"version": "1.0.0",
"description": "Project containing your PowerApps Component Framework (PCF) control.",
"scripts": {
"build": "pcf-scripts build",
"clean": "pcf-scripts clean",
"lint": "pcf-scripts lint",
"lint:fix": "pcf-scripts lint fix",
"rebuild": "pcf-scripts rebuild",
"start": "pcf-scripts start",
"start:watch": "pcf-scripts start watch",
"refreshTypes": "pcf-scripts refreshTypes",
"bundle": "webpack",
"type": "module"
},
"dependencies": {
"@here/maps-api-for-javascript": "^1.57.0",
"@microsoft/eslint-plugin-power-apps": "^0.2.33",
"@types/node": "^18.19.31",
"@types/powerapps-component-framework": "^1.3.11",
"@typescript-eslint/eslint-plugin": "^7.7.1",
"@typescript-eslint/parser": "^7.7.1",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"ts-loader": "^9.5.1",
"webpack": "^5.94.0",
"webpack-cli": "^5.1.4"
},
"devDependencies": {
"@here/maps-api-for-javascript": "^1.57.0",
"@microsoft/eslint-plugin-power-apps": "^0.2.33",
"@types/node": "^18.19.31",
"@types/powerapps-component-framework": "^1.3.11",
"@typescript-eslint/eslint-plugin": "^7.7.1",
"@typescript-eslint/parser": "^7.7.1",
"eslint": "^8.57.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.1.1",
"pcf-scripts": "^1",
"pcf-start": "^1",
"ts-loader": "^9.5.1",
"typescript": "^4.9.5",
"webpack": "^5.94.0",
"webpack-cli": "^5.1.4"
}
}