I create a react app using the cli called create-react-app. Look like Facebook did lots of things underneath, such as webpack etc. However, I guess it may also has some limitations. I try to follow this tutorial to load google map api. And when I debug my code, I can see the google map has been successfully referenced..
But then I click play and let application finishes running. I got google is not defined error from webpackHotDevClient.js and my application crashes.
Since webpack compile the files on the fly, I assume it has trouble to load google map via https?
Any thoughts?
As mentioned in the user guide, you need to explicitly read any global variables from window. Put this at the top of the file and it will work:
const google = window.google;
The reason we enforce this is because people commonly misunderstand the difference between local variables, imported modules, and global variables, and so we want to always make it clear in the code when you use a global variable.
By the way, this is not related to Webpack or HTTPS. You see this because we use a linting rule that forbids unknown global variables.
I think the google variable is already available when you import google map from script in html. This error caused by Eslint, you can try and add the below line to the top of your file to disable ESlint
/*global google*/
I have a better solution then #Dan's you can do it like this
window.google = window.google ? window.google : {}
OR
const google = window.google = window.google ? window.google : {}
If google is available then no problem if not then empty Object will be temporarily assigned till your scripts are loaded.
In case es-lint throws undefined google error, update the globals in eslint configuration file:
{
"globals": {
"google": "readonly"
}
}
OR
For a specific file use case define like below on the top of the file
/*global google*/
Hi you can use withGoogleMap like so:
import { withGoogleMap, GoogleMap, Marker, InfoWindow } from "react-google-maps";
const google = window.google;
class MapComponent extends Component {
....
<GoogleMap>
.....
.....
.....
</GoogleMap>
export default withGoogleMap(MapComponent);
.eslintrc.json
{
// ...
"globals": {
"google": "readonly"
}
}
yarn add #types/googlemaps
OR
npm i --save #types/googlemaps
Related
I am using a userFunction to query the property database in a custom Forge Viewer extension. This works great while testing the site locally using npm run serve. However, when I deploy the website to the web (which uses npm run build), the function no longer executes. The error says: SyntaxError: Function statements require a function name. This is because, according to the documentation, the function executed through executeUserFunction has to be named userFunction.
Upon further inspection I discovered that this was because of Vue & Webpack's mangling feature (executed by terser-webpack-plugin), where it renames variables and removes function names to decrease file size.
I have tried many different things, from making the function part of the extension's class to moving it to the global JS scope, but nothing helped. I also tried to exclude objects.js (which is the name of the extension I wrote) from mangling, but this didn't work either.
How do I configure terser to stop mangling this one variable?
I eventually figured out a way to do this which worked:
Add the following to vue.config.js:
module.exports = {
...
chainWebpack: config => {
config.optimization.minimizer('terser').tap(args => {
// eslint-disable-next-line no-param-reassign
args[0].terserOptions.keep_fnames = true;
return args;
});
},
};
This will prevent terser from removing function names, and will make it so userFunction still works. Weird design choice by Autodesk to require a function name, but at least it works now :)
Is it possible to open a custom extension thorough another custom extension ?
I tried but I get issues at the time of "Autodesk.Viewing.UI.DockingPanel.call" not sure whether I have done it properly or it is possible at all .
My use case :
I need to create a report, which contains some additional data that needed to enter at runtime plus a screenshot of the current view.( for this i have one extension).
Above extension need to open through markup extension so I can add annotation and save the screenshot.
Cheers
edit
is it possible to add a custom extension to a core extension as well ?
viewer.loadExtension("Autodesk.Viewing.MarkupsGui").then(function (extension_)
{
viewer.loadExtension('CreateNcrExtension');
});
This actually doesn't work . No error but wont load as well
Loading extensions from another extension is common, and usually done in your extension's load method. The load and unload methods can be async, so you can do something like this:
class MyAwesomeExtension extends Autodesk.Viewing.Extension {
// ...
async load() {
await this.viewer.loadExtension('Autodesk.Viewing.MarkupsCore');
return true;
}
// ...
}
I am trying to show a diff for two JSON objects in Angular 4 view, I am using this library (angular-object-diff) originally built for AngularJS.
Demo of that library: Link
I tried to import this JS library the following way:
JS file I am trying to import: angular-object-diff.js, doesnt have a exported variable
In my typings.d.ts ( I added the following):
declare var ObjectDiff: any;
In my angular-cli.json, I added
"scripts": [
"../node_modules/angular-object-diff/dist/angular-object-diff.js"
],
In my component file:
const json1 = {
name: 'John'
};
const json2 = {
name: 'Johnny'
};
const diff = ObjectDiff.diffOwnProperties(json1, json2);
this.jsonViewData = ObjectDiff.toJsonDiffView(diff);
In my view:
<pre ng-bind-html="jsonViewData"></pre>
<pre> {{jsonViewData}}</pre>
Nothing seems to be working, I get the error that "ObjectDiff" is not defined in the console"
Can someone please let me know if I am doing in thing wrong ?
Suggestions for displaying the JSON diff are also welcomed :)
** Thank you
The library doesn't export anything. It uses IIFE to not pollute global scope with local variables. It's impossible to reach local variables from the outside, this makes Module pattern so effective (and annoying).
The library uses AngularJS angular global and expects that it will exist. This creates a problem, because Angular 4 application should mock angular global in this case. Moreover, the code itself relies on AngularJS-specific units ($sce service).
The library should be forked and modified to suit the expectations. The mentions of angular should be removed. Considering that script will be executed in module scope, IIFE should be removed and appropriate exports should be added.
I currently try to use google map API with react js and babel. I don't want to use the existing react components (that are uncomplete).
The problem I encounter is that I can't load the google map object. Babel always show me a compilation error like this one :
error 'google' is not defined
Event if I load the google map script in my index :
<script src="https://maps.googleapis.com/maps/api/js?key=MY_KEY&libraries=places&callback=initAutocomplete" ></script>
I understand that babel doesn't load the google map library at compile time, but try to compile some code lines like this :
var map = new google.maps.Map(document.getElementById('map')...
Is there someone who know how to handle this case ?
Thank you
Install the google maps api npm module and import it into your relevent files. https://www.npmjs.com/package/google-maps
I am currently learning Meteor and I found out something that intrigued me.
I can load HTML and CSS assets from a JS file using the import statement.
import '../imports/hello/myapp.html';
import '../imports/hello/myapp.css';
import * as myApp from '../imports/hello/myapp.js';
This was a surprise to me so I ran to google but could not find this behavior documented in the specification for ES6 import or in Meteor's Docs.
So my questions are:
Can I rely on this behavior to build my apps?
Will my app will break when Meteor gets around to fix it -- if it's a bug --?
Notes
I am using Meteor v1.3, not sure if this works also with previous versions.
You can download the app to see this behavior from Github
After going through the implementation of the built files for my app
I found out why this works.
HTML
Files are read from the file system and their contents added to the global Template object, e.g.,
== myapp.html ==
<body>
<h1>Welcome to Meteor!</h1>
{{> hello}}
</body>
results in the following JS code:
Template.body.addContent((function () {
var view = this;
return [
HTML.Raw("<h1>Welcome to Meteor!</h1>\n\n "),
Spacebars.include(view.lookupTemplate("hello"))
];
}));
Which is wrapped in a function with the name of the file as it's key:
"myapp.html": function (require, exports, module) {
Template.body.addContent((function () {
var view = this;
return [
HTML.Raw("<h1>Welcome to Meteor!</h1>\n\n "),
Spacebars.include(view.lookupTemplate("hello"))];
}));
Meteor.startup(Template.body.renderToDocument);
Template.__checkName("hello");
Template["hello"] = new Template("Template.hello", (
function () {
var view = this;
return [
HTML.Raw("<button>Click Me</button>\n "),
HTML.P("You've pressed the button ",
Blaze.View("lookup:counter",
function () {
return Spacebars.mustache(view.lookup("counter"));
}), " times.")
];
}));
},
So all of our HTML is now pure JS code which will be included by using require like any other module.
CSS
The files are also read from the file system and their contents are embedded also in JS functions, e.g.
== myapp.css ==
/* CSS declarations go here */
body {
background-color: lightblue;
}
Gets transformed into:
"myapp.css": ["meteor/modules", function (require, exports, module) {
module.exports = require("meteor/modules").addStyles("/* CSS declarations go here */\n\nbody {\n background-color: lightblue;\n}\n");
}]
So all of our CSS is also now a JS module that's again imported later on by using require.
Conclusion
All files are in one way or another converted to JS modules that follow similar rules for inclusion as AMD/CommonJS modules.
They will be included/bundled if another module refers to them. And since all of them are transformed to JS code
there's no magic behind the deceitful syntax:
import '../imports/hello/myapp.html';
import '../imports/hello/myapp.css';
They both are transpiled to their equivalent forms with require once the assets have been transformed to JS modules.
Whereas the approach of placing static assets in the imports directory is not mentioned in the official documentation,
this way of importing static assets works.
This seems to be at the core of how Meteor works so I'd bet this functionality is going to be there for a long while.
I don't know if to call this a feature maybe a more appropriate description is unexpected consequence but that would
only be true from the user's perspective, I assume the people who wrote the code understood this would happen and perhaps even
designed it purposely this way.
One of the features in Meteor 1.3 is lazy-loading where you place your files in the /imports folder and will not be evaluated eagerly.
Quote from Meteor Guide:
To fully use the module system and ensure that our code only runs when
we ask it to, we recommend that all of your application code should be
placed inside the imports/ directory. This means that the Meteor build
system will only bundle and include that file if it is referenced from
another file using an import.
So you can lazy load your css files by importing them from the /imports folder. I would say it's a feature.
ES6 export and import functionally are available in Meteor 1.3. You should not be importing HTML and CSS files if you are using Blaze, the current default templating enginge. The import/export functionality is there, but you may be using the wrong approach for building your views.