Search code examples
javascriptnode.jsinputnpmparceljs

Error: HTML onClick not defined with Node.js, NPM and Parcel


I am making a weather application.

To develop this I am using Node.js with NPM and Parcel. (I need to do this, because otherwise OpenLayers won't work, but I have not worked with it before.)

I need to be able to work with user-input. For example I want the user to click on a button and then something needs to happen.

Below a very simple explanation what I need to accomplish.

The button, which I need to be in the index.html

<input type="button" name="bt" value="test" onclick="clickKnop()">

Function that needs to be executed after click, which I need to be in the index.js

    function clickKnop(){
        console.log('Hello World'); 
    };

Of course in my application the function needs to be different, but that is not my problem.

When I am coding in the Node.js environment it works ONLY when I put the clickKnop function in the script part of my HTML.

When I put the function in my index.js file, it doesn't work anymore. I get the following error: Uncaught ReferenceError: clickKnop is not defined at HTMLInputElement.onclick

This also happens when I use the created /dist files on my server on which they will be presented once the application is finished.

How can I make this work?

Hope you guys can help!!

EDIT:

import Map from 'ol/Map.js';
import View from 'ol/View.js';
import TileLayer from 'ol/layer/Tile.js';
import OSM from 'ol/source/OSM.js';
import TileWMS from 'ol/source/TileWMS.js';
import {fromLonLat} from 'ol/proj';
import {ZoomSlider} from 'ol/control.js';

	/*
		Hieronder komt het stukje code voor de datum en tijd.
		Default moet present datetime zijn, afgerond op 10 min (naar beneden).
		Vervolgens moeten er stapjes van 10 minuten terug gemaakt worden om uit te kiezen.
		De eindgebruiker moet zelf ook een datetime in kunnen voeren welke dan opgehaald wordt.
		Hiervoor worden ook de stapjes van 10 minuten gebruikt.
	*/

	// Current datetime
	const date = new Date();
	
	//Round current datetime to last 10 min
	const coeff = 1000 * 60 * 10;
	const floorDate = new Date(Math.floor(date.getTime() / coeff) * coeff);

	//Format the current datetime so that it can be used as input for the WMS viewparams
	const floorDateFormat = new Date(floorDate.toString().split('GMT')[0]+' UTC').toISOString().split('.')[0].replace('T',' ');
	
	console.log(floorDateFormat);
	
	
	// -10 minutes from current time + formatting for input viewparams
	const minusTenMinutes = floorDate;
	minusTenMinutes.setMinutes(minusTenMinutes.getMinutes() - 10);
	const minusTenMinutesFormat =	new Date(minusTenMinutes.toString().split('GMT')[0]+' UTC').toISOString().split('.')[0].replace('T',' ');
	
	console.log(minusTenMinutesFormat);
	console.log(floorDate);


	/*
		Hieronder wordt de map gemaakt.
		De verschillende layers en layergroepen worden aangeroepen.
		De viewparams + datetime moet mee gaan met de hierboven gedefinieerde datetime
		Daarnaast moet de gebruiker ook kunnen wisselen tussen de verschillende weersoorten,
		hiervoor moeten de params geüpdatet worden.
	*/
	let datetime = "2018-10-16 08:00:00";
	
	//Base Europe
	const wmsSourceBaseLayer = new TileWMS({
      url: 'http://localhost:8080/geoserver/O/wms',
      params: {
        'LAYERS': 'O:Europe_Polygons',
        'TILED': true
      },
      serverType: 'geoserver',
      crossOrigin: ''
    });

    const wmsBaseLayer = new TileLayer({
      source: wmsSourceBaseLayer
    });
	
	//Weather || DEFAULT TEMPERATURE
	const wmsSourceTemperature = new TileWMS ({
      url: 'http://localhost:8080/geoserver/O/wms',
      params: {
        'LAYERS': 'O:Temperature',
        'TILED': true,
		'viewparams': 'chosen_timestamp:' + datetime
      },
      serverType: 'geoserver',
      crossOrigin: 'anonymous'
    });
	
	const wmsWeatherLayer = new TileLayer({
		source: wmsSourceTemperature
	});

	//Update de params zodat er ander weer komt
	//wmsSourceTemperature.updateParams({'LAYERS': 'Observations:observations_v'});
	
	//LonLat of germany converted for use in view
	const germanyLonLat = [10.018343, 51.133481];
	const germanyConvertedLonLat = fromLonLat(germanyLonLat);
	
	//Making a view for the map
    const view = new View({
      center: germanyConvertedLonLat,
      zoom: 5
    });
	
	//Building the map with the layers
    const map = new Map({
      layers: [wmsBaseLayer, wmsWeatherLayer],
      target: 'map',
      view: view
    });
	
  
  
  
  
	function clickKnop(){
		console.log('Hello World');	
	};
    
<head>
  <title>Tiled WMS</title>
  <!--<meta http-equiv="refresh" content="10"/>-->
  <link rel="stylesheet" href="https://openlayers.org/en/v5.3.0/css/ol.css" type="text/css">
  <style>
    #map {
      width: 450px;
      height: 500px;
	  border: 3px solid grey;
    }
  </style>
</head>

<body>
		<div id="map" class="map"></div>
		<script src="./index.js"></script>
		<input type="button" name="bt" value="test" onclick="clickKnop()">
</body>

Now it is kind of a mess, but what I want to accomplish is that the different geoserver WMS-layer gets called with different params depending on time.

To do this I want input from my HTML (and I also want to make a button to go back in steps of 10 minutes).

So I want to make functions that call the WMS-layers that change the time variable.

Again, the code that I have now is really messy, but I am still working on it, so please look past that..

Hope this helps...


Solution

  • It looks as though you have confused the difference between frontend and backend scripting.

    You will have to develop a frontend application that will be able to talk to your node.js application. Your HTML code cannot read the NodeJS source code and that's why you're getting the error Uncaught ReferenceError: clickKnop is not defined at HTMLInputElement.onclick.

    By the looks of it, you will have to separate out your frontend code to call endpoints on your NodeJS application using something like https://expressjs.com/.

    An example of this would be:

    Frontend using JQuery

    <body>
    <a id="UpdateMap">Update Map</a>
    <script src="jquery..." />
    <script>
        $('#UpdateMap').click(function(){
           $.get( "myNodeJSServer:Port/UpdateMap", function( data ) {
              $( ".map" ).html( data );
              alert( "Load was performed." );
            });
        });
    </script>
    </body>
    

    Backend using Express and NodeJS

    ...
    //In your NodeJS Express Routes Application Page
    app.get('/UpdateMap', function (req, res) {
      clickKnop();
    })