JavaScript method isn't working on view in Rails 6+ - javascript

I want to declare a method in a JS file and use it in the .html.erb like this below method
const getSetHtml = () => {
console.log("Hello World");
}
and in the view .html.erb like this below code
onclick="getSetHtml()"
but it's showing
Uncaught ReferenceError: getSetHtml is not defined
I imported files like below
// /app/javascript/application.js
import "#hotwired/turbo-rails";
import "controllers";
import "trix";
import "#rails/actiontext";
import "trix";
import "#rails/actiontext";
import "./bootstrap.bundle.min";
import "./editor"; // this file
Note: Others JS library is working fine but the custom method isn't working.
Thanks

Why do you want to set the function with const? If it fits with your specific use case, cool! Otherwise I would personally just go ahead and define it regularly, either way here is the syntax for what you're trying to do.
const getSetHtml = function() {console.log("Hello World")};
Your current function returns the function itself rather than returning the return value of the function(the console.log("Hello World")).
I can't be entirely sure but I believe in your application.js you can just import the file like this I would try the other thing first: import "editor";
I hope this helps even a little, good luck. Let me know how it goes!

You can expose your function by adding it to the global object
global.getSetHtml = () => {
console.log("Hello World");
}

Related

webpack doesnt add prototype function to Object from other file

I have a file containing the definition of a Object and in that same file I have a function that is part of this object like so:
export function ARScene(_callbacks) {
this.callbacksObject = _callbacks;
// more fancy code..
}
ARScene.prototype.changeCar = function() {
//some fancy code here
this.loadHDCar(); // THIS LIKE GENERATES A ERROR.
}
now I have a different file containing an other method that is part of the Object called ARScene like so:
import { ARScene } from './arScene';
ARScene.prototype.loadHDCar = function() {
//some more fancy code..
}
What is happening when I build this with webpack and run it in the browser I get the error that this.loadHDCar(); is undefined I guess this happens because webpack doesnt add a file if it is not imported. But how do I make sure that ARScene.prototype.loadHDCar is added to the object in the final output?
I am a complete newbie to webpack and modules. I have found answers on stackoverflow about this but they had slightly different scenarios then me. So their solutions didnt work (or maybe I didnt understand it).
If more context or information is needed please let me know.
How do I make sure that ARScene.prototype.loadHDCar is added to the object in the final output?
You should import it in the arScene module, and you should even create the prototype method in there (where you are defining the class) for visibility.
export function loadHDCar() {
… //some more fancy code
}
import { loadHDCar } from './loadHDCar';
export function ARScene(_callbacks) {
…
}
ARScene.prototype.loadHDCar = loadHDCar;
ARScene.prototype.changeCar = function() {
… // some fancy code here
this.loadHDCar();
};

How to import and use function in another function in JS

I have a main file 'index.js' and I want to import and use the functions in it in another js file.
I tried importing the file using require but it did not work.Can someone help me with suggestion.
Index.js,
function dcLib() {
function test() {
console.log('Hi');
}
return {
test:test
}
};
export default dcLib;
column.js,
const dcLib = require('../index');
dcLib.test()
The above code giving error as
TypeError: dcLib.test is not a function
Either do:
const dcLib = require('../index');
dcLib.default().test();
... or, if you prefere it, you can do:
const dcLib = require('../index').default;
dcLib().test();
Or, in a simpler (ES6) fashion, just do:
import dcLib from './test';
dcLib().test();
ES6 imports and exports behaves differently if you're using require instead of import. Also, things changes a bit according to the environment and, eventually, the transpiler, if any is used. Read more about that here, where Felix Kling made a pretty exhaustive overview about such argument
As mentioned in the comment, I've made a working example to play with on stackblitz, feel free to play around with it with both cases: https://stackblitz.com/edit/js-3wwz8a?file=index.js

Calling an exported function by a string value of the function name

This is a very simple example of what I am trying to achieve, basically I want to call a function by a string value of it's name, e.g. "hello" should call hello()
I have a helper.js file which contains an exported function e.g.
export function hello() {
console.log('is it me you`re looking for?');
}
I am importing this into another js file for usage
import {hello} from './helper';
I have tried using eval, window and new Function to call my function but no luck
//getting console error "hello is not defined"
eval('hello()');
var fn = window['hello()'];
fn();
var fn = new Function('hello()');
fn();
If I wrap the function like so, the eval fires the wrapper.
function helloWrapper() {
hello();
}
eval('helloWrapper()');
I just cant seem to fire the exported hello() function directly. I have around 10 functions I'll need to fire so having a wrapper for each seems a bit hacky and wondering if there is a way I can achieve this?
Any help would be greatly appreciated if anyone can point me in the right direction.
Thanks in advance
eval("hello()") should work just fine -- but it's not how you should do this. :-)
Instead, build an object containing the functions:
import {hello} from './helper'; // In some environments, these need the
import {groot} from './groot'; // .js on the filenames.
// ...
const functions = {hello, groot/*, ... */};
and then call them like this:
functions[name]();
Live example on plnkr.co
Generally, referring functions by their names is unsafe in client-side code - or any other that can be minified. The approach explained in the question will work only because hello isn't just function name but an import. Due to how ES modules work, import names will be preserved on minification.
In order for a function to be referred by its name, it should be object property. In case of imports there's already such object, it's module export:
import * as helper from './helper';
helper['hello']();
In case there are multiple modules where functions may originate from, there should be intermediate module that re-exports them.
export * from './helper';
export * from './another-helper';
All functions from underlying modules will be available as properties when it's imported as *:
import * as helper from './reexported-helpers';
helper['hello']();
helper['bye']();

Share JavaScript file resources with another Javascript without using HTML

I need to use the functions of a javaScript file in another javaScript file, but I do not have an HTML linking the 2, how to share it?
const {Builder} = require('selenium-webdriver')
var chrome = new Builder().forBrowser('firefox').build()
login(chrome);
this is my code main and i need get this other method to other JavaScript File.
function login(chrome, user, senha){
chrome.get('https://testerbeta.crm2.dynamics.com/main.aspx');
}
now the code is small, but the software that I have to test is great and I need to separate the methods in different javascripts files
I think what you're looking for are import and export, added in ES6.
Basically, in the file you want to get your functions from, just add export keyword before function declarement, just like that:
export function foo() {
return bar;
}
Then, in the file you want to inject your function in, you add this at the beginning of the file:
import { foo } from 'path/to/your/file_with_function_to_export.js'
More about that you can read here.

Convert closure to es6 module

I'm using a javascript build environment that supports es6 modules (using es6-module-transpiler) so you can simply import stuff across different files.
Now I got a third party library that I'd like to be "importable".
The library populates its functionality like this:
(function () {/*...*/}).call(this);
Would it be safe to omit the closure and convert it to:
export default function () {/* ... */};
Or is there a better way?
Thanks in advance!
The original code you show invokes the anonymous function, which to make any sense must define a global variable, whereas the second code fragment you show merely exports the function, which is a different thing.
For purposes of discussion, let's assume the original code defines a global like this:
// my-third-party-module.js
(function() {
let myVar = 22;
window.MyThirdPartyModule = { log: function() { console.log(myVar); } };
}.call(this);
and you are using is as so:
// app.js
MyThirdPartyModule.log();
You could rewrite this as
// my-third-party-module.js
let myVar = 22;
export default { log: function() { console.log(myVar); } };
// app.js
import MyThirdPartyModule from `my-third-party-module';
MyThirdPartyModule.log();
Note that we have moved the variable myVar which was local to the anonymous function to the top module level.
However, depending on your preferences, rather than exporting a big object, which is sort of a pre-module mentality, you might want to export its APIs individually:
// my-third-party-module.js
let myVar = 22;
export function log { console.log(myVar); }
// app.js
import {log} from `my-third-party-module';
log();
or if you prefer
// app.js
import * as MyThirdPartyModule from `my-third-party-module';
MyThirdPartyModule.log();
However, all of these approaches assume you are able and willing to edit the source of the third party library. If that is not the case, you could write a little piece of glue code, such as
// my-third-party-module-interface.js
import 'my-third-party-module'; // This will run the module.
export default MyThirdPartyModule; // Export the global it defined.
// app.js
import MyThirdPartyModule from 'my-third-party-module-interface';
If you would prefer again to export individual APIs, you could extend the glue to re-export each of them:
// my-third-party-module-interface.js
import 'my-third-party-module'; // This will run the module.
const {log, otherAPI, ...} = MyThirdPartyModule;
export {log, otherAPI, ...};
// app.js
import {log} from 'my-third-party-module-interface';
The conversion of legacy dependencies is still an issue. And the horrible workflow they use makes things a lot harder, prefixing the actual code with browserify and webpack silliness.
So what to do? Existentially, the library is guaranteed only to deposit a global in window but by obscure and weird ways. And all slightly different.
So let the legacy simply do what it is supposed to do for you, but wrapped in a module so that you can import it rather than use a script tag:
https://medium.com/#backspaces/es6-modules-part-2-libs-wrap-em-up-8715e116d690

Categories

Resources