Angular4 - Use a function inside a JavaScript file - javascript

I'm trying to load a JavaScript file into my angular component. I have loaded the full minified version from here: https://github.com/blueimp/JavaScript-Load-Image/blob/master/js/load-image.all.min.js and also put any related scripts in my scripts folder.
When the code runs and reaches 'loadImage', the console fires an error:
ERROR ReferenceError: loadImage is not defined
What's the best way to resolve this?
Component
import '../../../assets/scripts/load-image.all.min.js';
declare var loadImage: any;
...
dropChangeHandler(e) {
e.preventDefault()
e = e.originalEvent
var target = e.dataTransfer || e.target
var file = target && target.files && target.files[0]
var options = {
maxWidth: 1000,
maxHeight: 1000,
canvas: true,
pixelRatio: window.devicePixelRatio,
// downsamplingRatio: 0.5,
orientation: true
}
if (!file) {
return
} else {
this.currentFile = file;
if (!loadImage(file, this.updateResults, options)) {
}
}
}
I think this question is slightly different to the other 'import JS files into angular' because I have a feeling it might be to do with the library I'm trying to import. However, I'm unsure and seeking advice on this one.

The library you are trying to import doesn't support es6 modules. Because of no exports in the library, it doesn't add any variables to your scope after import.
In your particular case easiest is to add the script to index.html:
<script src="assets/scripts/load-image.all.min.js"></script>
and call a method in the component with
window.loadImage(file, this.updateResult, options)
I use window because library directly binds itself to window.object
More details
To use javascript modules with typescript add allowJs: true to tsconfig.js file.
import './file is known as an import for side-effects only and don't change the scope of the module, but can access to global app scope. It can help you in case you want to extend already imported module.
You could import js module different ways:
For CommonJs modules it's possible to use import * as ModuleName from './modulePath.js'; in your component.ts file and call as ModuleName.exportedMethod().
to the Angular pipeline to be sure it is loaded with the module which
imports it. If you are using angular cli, simply include it to you
angular-cli.json in the section apps/scripts:
{
"apps":
...
"scripts": [
"assets/scripts/load-image.all.min.js"
]
}
If you don't use angular-cli, you can include to your index.html:
<script src="assets/scripts/load-image.all.min.js"></script>

I think you need to export the wanted function in your imported file.

you must unsusure that the library is will be compiled
Add the script in angular-cli.json
"scripts": [
....
'<path to file>/assets/scripts/load-image.all.min.js'
....
]
then
declare var loadImage: any;

Related

Import javascript from node_modules in angular

I installed a npm package which contains a javascript file, what I want to use. The js file name is all.js and contains this code:
import { initExtended } from './extended'
import Header from './components/header/header'
function initAll(options) {
// Set the options to an empty object by default if no options are passed.
options = typeof options !== 'undefined' ? options : {}
// Allow the user to initialise GOV.UK Frontend in only certain sections of the page
// Defaults to the entire document if nothing is set.
var scope = typeof options.scope !== 'undefined' ? options.scope : document
// Find first header module to enhance.
var $toggleButton = scope.querySelector('[data-module="govuk-header"]')
new Header($toggleButton).init()
initExtended(options)
}
export {
initAll,
Header
}
File all.js is located in node_modules.
When I tried to import it directly from index.html like:
<script type="module" src="node_modules/#id-sk/frontend/govuk/all.js"></script>
It is not working. Console error, file not found.
I also tried import it via angular.json:
"scripts": [
"./node_modules/#id-sk/frontend/govuk/all.js"
]
Also not working with error "Uncaught SyntaxError: Cannot use import statement outside a module (at scripts.js:15241:1)". The error refers to line:
import { initExtended } from './extended'
I also tried to import it in polyfills but I don't know how to call it.
As you are speaking about angular.json, I assume that you are working in an Angular application bootstrapped using the Angular CLI with default settings.
To be able to use this package #id-sk/frontend in your typescript files, you have to import it directly into your typescript file.
1. Import #id-sk/frontend in your TS files
// Import everything into a local variable
import * as govuk from '#id-sk/frontend';
// Import specific object
import { HeaderExtended } from '#id-sk/frontend';
2. Run ng serve
⚠ Spoil: It will lead to typings errors
3. Let's add or create typings
As #id-sk/frontend is not written in typescript, the compile doesn't know about the typings of this library.
Following this statement, you have two choices:
Find or contribute to DefinitelyTyped in order to create the typings of your package #id-sk/frontend
Create a local file typings.d.ts in your ./src folder to declare an empty module
declare module "#id-sk/frontend"
4. Kill & run ng serve again
Enjoy it!
Go further
You can add typings to your module in order to give you autocompletion on the provided objects of #id-sk/frontend.
``ts
declare module "#id-sk/frontend" {
export interface Options {
scope?: Document
}
export function initAll(options: Options): void;
}

Referencing vanilla js file in TypeScript getting file is not a module

I'm trying to import a file into TypeScript that's basically just a js file that you'd put into a tag. I've tried a few different things.
// global.d.ts
declare module 'myfile.js'
Inside of the react file:
// component.tsx
import { foo } from '../lib/myFile.js' // This is saying it is not a module
Inside of the js file, it looks like this a few times so not sure how I need to reference the file:
(function( something ) {
something.Foo = function (){}
}(window.something = window.something || {}));
Any thoughts on how I could use this file? Do I need to go through and declare typings for everything in it?
EDIT: I've added allowJS to my tsconfig but it still doesn't work.
You can only import what is exported from the file.
If your file contains only immediately invoked functions, or top level code, you only need to import the file itself like this:
import '../lib/myFile.js'
This is a little weird, however. I would suggest wrapping everything with a function and exporting then importing that function instead.

How do I call a function in an external js file using typescrpt

We are trying a POC of adding Typescript and Webpack to our Angularjs project.
I am able to get my webpack bundle to generate, however at runtime the program cannot find the various functions in my validator.js. Can you please offer some advice?
login-view.components.ts
declare var findFormNode: any; //function in validator.js
//LogInUser
self.login = function ($event, command) {
if (findFormNode($event.target.id)) {
...
}
}
main.ts is importing the file
import "./../../../CommonStaticFiles/include/js/Validators.js";
bundle.js
eval("/* WEBPACK VAR INJECTION */(function($) {/*\r\n\r\n VALIDATORS\r\n\r\n ... n\n\nfunction findFormNode(
error
ReferenceError: findFormNode is not defined
at LoginController.self.login (login-view.component.ts:28)
at fn (eval at compile (angular.js:NaN), <anonymous>:4:267)
at callback (angular.js:29019)
In order for your functions to be properly imported, there are few things that you have to make sure of.
First, make sure you are exporting your functions correctly. Here's an example of how to export a function from Validator.js:
export const validateFunc1 = ():void => {};
Next, you have to make sure you are using proper import syntax. In order to import the function above, you would do the following:
import {validateFunc1} from "./../../../CommonStaticFiles/include/js/Validators.js";
Alternatively, if you want to import all exported functions at once, then you can use this syntax:
import * as validatorFuncs from "./../../../CommonStaticFiles/include/js/Validators.js";
Lastly, check that the location of Validators.js is correct. It's a common mistake to be looking in the wrong directory. Your code editor can usually help you find the right path to use.

Import array of modules (MDBootstrap js modules) into Laravel Mix

I have a fresh Laravel 5.8 installation and I would like to include the js modules from MDBootstrap.
In my bootstrap.js file I have:
require('./mdb/modules');
The ./mdb/modules.js file has:
exports.modules = [
'./js/_intro-mdb-pro.js',
'./js/scrolling-navbar.js',
'./js/vendor/jquery.easing.js',
'./js/vendor/velocity.js',
'./js/vendor/chart.js',
'./js/vendor/wow.js',
... 30 more
];
The compilation works ok, but of course, it doesn't take any effect from these modules include.
I don't know how to include all of them at once as they are not looking like a regular module so I can import like 'import * from 'my-module'
I also tried the ES6 way:
import * as MDBootstrap from './mdb/modules';
but I got the same result: successful compilation without including them into the compiled js file.
The content of these 'modules' doesn't seem to look like a normal module where we export default {} or some other functions or variables. It looks like:
//mdb/js/scrolling-navbar.js
"use strict";
(function ($) {
var SCROLLING_NAVBAR_OFFSET_TOP = 50;
$(window).on('scroll', function () {
var $navbar = $('.navbar');
if ($navbar.length) {
if ($navbar.offset().top > SCROLLING_NAVBAR_OFFSET_TOP) {
$('.scrolling-navbar').addClass('top-nav-collapse');
} else {
$('.scrolling-navbar').removeClass('top-nav-collapse');
}
}
});
})(jQuery);
Even 'exports.modules = [..]' is not familiar to me. I know about 'module.export = ...' but this 'exports' looks like it's a Node.js object.
I know there's also another method to include the dist version of the plugin. I also tried it, but I got some errors: 'Identifier '_classCallCheck' has already been declared'. I looked deeper and I found that actually many of those files are declaring the '_classCallCheck' function and of course that it a redeclare error. Maybe I can refer to this particular error directly to them (MDBootstrap).
So here I am, trying to include and use these modules/files in my Laravel project without success. Any help is appreciated.

Using JQuery etc. in TypeScript with RequireJS [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to require jquery via AMD in TypeScript
I created a project in TypeScript. I use RequireJS. Everything was working fine, until I need JQuery...
This is my files structure:
As you can see, I have jquery-1.8.d.ts file in the modules folder. The .js file for jQuery is inside the lib folder. When I import a module using the config file for RequireJS:
/// <reference path="../modules/require.d.ts" />
/// <reference path="AppMain.ts" />
require.config({
baseUrl: '../',
paths: {
jquery: 'lib/jquery-1.8.3'
},
shim: {
jquery: {
exports: '$'
}
},
name: "app/AppMain",
out: "../!built/Test.js",
optimize: "none"
});
require(['jquery', 'app/AppMain',
],
($, main) => {
var appMain = new main.AppMain();
appMain.run();
});
... then it's imported in JavaScript. What to do if I want it inside TypeScript? I need to use JQuery, JQueryStatic and JQueryPromise, declared inside .d.ts file.
When I try simply import a new module, I get an error:
import JQueryExternal = module("../../../modules/jquery-1.8.d"); // error: The name does not exist in the currect scope. A module cannot be aliased to a non-module type
interface Test {
MyMethod(): JQueryPromise; // here's a sample usage
}
In the beginning I thought that the path is wrong, but I tried to move it inside classes folder and next I imported it in such a way as the rest of classes. Same error:/
How to use jQuery in TypeScript in a way I want to? Is it possible?
This is completely confused:
import JQueryExternal = module("../../../modules/jquery-1.8.d");
You don't import the definition file as a module in order to use it in TypeScript. Whether you are using AMD/RequireJS or Node.js style modules to import the eventual code, you always reference d.ts definition files in the same way, at the top of your document:
/// <reference path="YOUR-RELATIVE-PATH-HERE/jquery.d.ts" />
This doesn't make the library available in JavaScript, but it will make the definitions available as you write your TypeScript.
I'm working on a large application similar in scope to yours which makes heavy use of RequireJS and JQuery. I can't see any benefit to loading JQuery as a module. I just import the reference (as described above), and make sure my page loads JQuery (and any other libraries) first:
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.2.min.js"></script>
<script type="text/javascript" src="//ajax.aspnetcdn.com/ajax/jquery.ui/1.9.0/jquery-ui.min.js"></script>
... etc ...
<script type="text/javascript" src="/content/client/libs/require.js" data-main="/content/client/pe.framework"></script>
I had some trouble with these two playing nicely together, so when I use requireJS with JQuery, I use a bundled version that loads them both. I don't know typescript, though, so I'm not sure how helpful this will be.
Link to the bundle: https://github.com/jrburke/require-jquery

Categories