Using an external React component on Rails application - javascript

I am trying to use the rc-slider React component on a existing Rails application that is using react-rails gem and it already have some other components that were built within the application that work just fine.
Based on this blog post I've been able to follow its first 3 steps, I've found the minified and browser-ready version of it here, added the file to the suggested path and required it on the application.js as recommended but even seeing the code within the Sprockets generated application javascript file that is rendered on the browser I can't see or use the supposed global variable it would provide according to step 4.
In the component's examples page it uses a const Slider = require('rc-slider'); statement in order to get that available. I've tried that but without luck as it throws: Uncaught ReferenceError: require is not defined. The same happens when I try the README usage's section approach: import Slider, { Range } from 'rc-slider';. I've tried both from an existing JS where I load other React components and also from the browser's Dev Tools Console window.
Am I using the wrong approach to the problem or maybe missing/overseeing any concept or basics here?

If you want to use Sprockets, you can get a pre-compiled version of rc-slider from unpkg:
https://unpkg.com/rc-slider#6.0.0/dist/rc-slider.js
Taking a look at the source, I see it exports the library as rc-slider:
So you can access it as window["rc-slider"] and use it from there, for example:
var RCSlider = window["rc-slider"]
var container = document.getElementById("container")
ReactDOM.render(
<div>
<RCSlider />
<RCSlider.Range />
</div>,
container
);
jsfiddle
That way, if you put rc-slider.js in the asset pipeline, you can use RCSlider in your javascripts.

Related

Why does my D3 code break when I set the script type to module?

I am working on a project built with Javascrpt, jQuery, and Vite.js. My colleague built a data visualization using D3 - a US states map - that I need to implement in the project on a specific page. They built the component using test data, my job is basically to load the component onto a page passing it actual returned data from an API call.
Everything in the test project works perfectly, but when I tried to implement this code into a script file in the project - literally copying and pasting from the working version - I got an error saying certain properties could not be read. After failing to debug for sometime, I randomly tried removing type="module" from the script tag link in HTML, and boom, everything worked. Does anyone have an idea of why this would be? I cannot get this code to run when the script type is set to module, except I need the script type to be set to module since I'm importing lots of components for other aspects of the page.
With the way the CodePen is set up, I couldn't replicate the issue since the HTML and JS files are automatically linked. But if you copy this code into your editor, and then in the html, set the the JS file to a module ` You'll see the issue.
Thanks. I'm at a total loss for what to do here. I could put all the D3 code in it's own script file, but then I have no way pass it variables from other files if it's not a module.
Per the comments, the following lines in my original code were not working in strict mode:
this.uStates = uStates;
this.uStatePaths = uStatePaths;
The fix was simple, I just needed to write the following instead:
window.uStates = uStates;
window.uStatePaths = uStatePaths;

Can I use a React app as a component on a static HTML page

I'm new to React and JS, and working with react-csv-viewer.
It works as expected and I can build and deploy it on a local server. But I do not require this, I just want to integrate the app as a component of a static HTML page.
I've tried following the process listed on the React tutorial for this, but I have trouble understanding the build process and how can I achieve this.
All I wish to achieve is to be able to use <CsvViewer /> provided by the author, possibly like this
const rootElement = document.getElementById("root");
ReactDOM.render(<CsvViewer />, rootElement);
and get the viewer app rendered at my HTML file, without building and deploying the viewer app on a (local) server.
Will appreciate any help or hints in this regard.
You can add React as it was shown in the tutorial you linked. The downside is that, you can't use JSX syntax (as it should be converted to JS during build time as it's not recognized by browsers as so).
Here is a post explaining how you can do so without transpilaton steps.
https://codepen.io/alexkrolick/post/react-without-a-build-step
Alias React.createElement, and call it to create components.
e.g.)
const h = createElement // convenient alias
// Instead of
<div className="foo" />
// create an element like so
h("div", { className: "foo" })
For more info on how that works, check out the official documentation.
https://reactjs.org/docs/introducing-jsx.html#jsx-represents-objects
But I really doubt anyone writes React code that way without a transpilation step in real life.
Would creating a separate site/page with React be a problem by chance? You can check out ParcelJS to easily create a React site if you aren't familiar with transpilation.

Using existing cljs components in a React project?

https://www.reddit.com/r/Clojure/comments/4el0xi/how_to_use_an_existing_reactjs_component_with/
There is this existing post about using existing ReactJS components in a CLJS/Reagent project. I'm looking to do the opposite. I have a bunch of CLJS components and would like to compile them into a ui library of some sort so that they can be used by React developers. That is, if I have a button CLJS component, I would like to be able to render that Button using < Button /> or mylib.Button(_) etc.. in a React/js app file.
I have read this - https://shadow-cljs.github.io/docs/UsersGuide.html#target-node-library - extensively but it's not quite working out. I've been using ":target :node-library" and I can get simple functions (that return strings/numbers, for example) to compile and work in my app, etc.. but it doesn't work for entire components. For example, my cljs button component takes in :
defn button [props & children]
but when I try to pass in these parameters (I call {lib.button({}, {})} in my App.js file), I get errors like "No protocol method IMap.-dissoc defined", because I'm trying to pass JS objects into CLJS-only functions, I believe. Not sure how to resolve this..
I can explain more on this if it would help clarify. It would also be super helpful if anyone had a reference demo project or any resources they could link me to.
I only have a few suggestions:
You can try to build a new sample project to consume your library with lein new figwheel myproject and use JavaScript interop to move one step at a time closer to the native JS way of using your library.
You can create an interface namespace that can consume JS objects and wrap these into Clojure data structures to sort out the protocol errors you're seeing, eg. functions that take a props parameter and pass down (js->clj props) to the rest of the code underneath.
For the authoritative source, check the Reagent docs, especially this: http://reagent-project.github.io/docs/master/InteropWithReact.html#creating-react-components-from-reagent-components

Loading customer sapui5 library inside component.js

According to the documentation here:
https://scn.sap.com/thread/3502503
http://jsbin.com/openui5-notepad-control-with-its-own-library-used-in-xmlview/1/edit?html,output
I build the following folder structure with following files:
/my/themes/sap_bluecrystal/library.css
/my/library.js
/my/Square.js
Now I am asking me how to load the library (inside Component.js) correct.
I tried following in Component.js
jQuery.sap.registerModulePath("my", "./my");
And in some View:
jQuery.sap.require("my.Square");
...
new my.Square({
text : "Test",
size : "200px"
})
All in all the Square control seems to be usable but the library.js and library.css is not loaded at all.
Any idea how to do it right?
Using bootstrap XML code inside index.html would not work if the app is running inside Fiori Launchpad.
Bonus question: Where to deploy a custom library inside SAP to be usable by multiple apps? One idea (but maybe that's wrong) is to create a BSP application just containing the library code?
The right way to load the library would be (instead of jQuery.sap.require):
sap.ui.getCore().loadLibrary("my");
This will load a "library-preload.json" file (if available) and also include the theme resources.
See https://openui5.hana.ondemand.com/#docs/api/symbols/sap.ui.core.Core.html#loadLibrary
First question I could solve for my own:
Replace
jQuery.sap.require("my.Square");
with
jQuery.sap.require("my.library");
Second question is still open :)

Including an external javascript library in pebble js file?

Is there any way I can include an external JS library in my pebble code?
Conventionally on a webpage I would do this in my head tags:
<script type='text/javascript' src='https://cdn.firebase.com/js/client/1.0.11/firebase.js'></script>
But in pebble, I am unable to do that since I am only using JS. So how can I include an external library for a JavaScript file.
At present, you cannot include external JS files.
If you're using CloudPebble, then the only way to do this is to copy and paste the content of the JS library files into your JS file.
If you're doing native development, you can modify the wscript file to combine multiple JS files into one at build time.
I think there's some confusion over Pebble.js vs PebbleKit JS (v3.8.1). Pebble.js is a fledgling SDK where eventually the programmer will be able to write pure JavaScript. It's still cooking so there's some functionality missing like the ability to draw a line or obtain the screen dimensions. The repo is a mix of C and JS sources where you can add C code to augment missing functionality but otherwise all your code lives in src/js/app.js or src/js/app/. Anyway, Pebble.js does support require.
I don't use CloudPebble but I got the impression that it either supports Pebble.js (and hence require) or is planning to. I think all this SDK boilerplate code would be hidden.
PebbleKit JS does not support require out of the box AFAIK. I've made a demo that ports require support from Pebble.js to PKJS. The summary of changes is:
Move your project's src/js/pebble-js-app.js to src/js/app/index.js.
Remove any ready event listener from src/js/app/index.js. index.js will
be loaded when the ready event is emitted.
Add src/js/loader.js from Pebble.js.
Add a src/js/main.js that calls require('src/js/app') on the ready event.
Update your wscript with the following
deltas.
When adding new modules, place them under src/js/app/ and require('./name') will work.
I've tried to cover this all in the demo's readme.
BTW, here's the official breakdown of all the different SDKs but it's a little confusing.
I am not sure if there have been changes since the above answer, but it looks like there is in fact a way to include additional resources while keeping things tidy. On the pebbleJS page, there is the following section with an some information on the subject.
GLOBAL NAMESPACE - require(path)
Loads another JavaScript file allowing you to write a multi-file project. Package loading loosely follows the CommonJS format. path is the path to the dependency.
You can then use the following code to "require" a JS library in your pebble project. This should be usable on both Cloud Pebble as well as native development.
// src/js/dependency.js
var dep = require('dependency');
You can then use this as shown below:
dep.myFunction(); // run a function from the dependency
dep.myVar = 2; // access or change variables
Update:
After some digging into this for my own, I have successfully gotten CloudPebble to work with this functionality. It is a bit convoluted, but follows the ECMAScript 6 standards. Below I am posting a simple example of getting things set up. Additionally, I would suggest looking at this code from PebbleJS for a better reference of a complex setup.
myApp.js
var resource = require('myExtraFile'); // require additional library
console.log(resource.value); // logs 42
resource.functionA(); // logs "This is working now"
myExtraFile.js
var myExtraFile = { // create a JSON object to export
"value" : 42, // variable
functionA : function() { // function
console.log("This is working now!");
}
};
this.exports = myExtraFile; // export this function for
// later use

Categories

Resources