Unable to import one Svelte component into another - javascript

I've been really intrigued by Svelte when I went through the documentation yesterday, but I'm struggling to set up even a pretty basic project and I can't seem to figure out what I'm doing wrong.
I'm starting out with the following HTML :
<!doctype html>
<html>
<head>
<title>My first Svelte app</title>
</head>
<body>
<main></main>
<script src='App.js'></script>
<script>
const application = new App({
target: document.querySelector( 'main' ),
data: {
name: 'world'
}
});
</script>
</body>
</html>
Then, I create the following App.html component :
<div class="app">Hello {{name}}</div>
<div class="lines"></div>
<script>
export default {}
</script>
I run svelte compile --format iife App.html > App.js, and everything works fine.
So far, so good!
Now, I create a Line.html component with the following content :
<div class="line">{{value}}</div>
<script>
export default {}
</script>
I modify my App.html component like this :
<div class="app">Hello {{name}}</div>
<div class="lines"></div>
<script>
import Line from './Line.html';
export default {
oncreate() {
const line = new Line({
target: document.querySelector( 'lines' ),
data: {
value: 'test'
}
});
}
}
</script>
I would expect this code to add something like <div class="line">test</div> to the DOM as a child of <div class="lines"></div>.
However, I get the following warning when I compile this code :
No name was supplied for imported module './Line.html'.
Guessing 'Line', but you should use options.globals
And when I try to run the compiled code, I just get the following output in my console :
App.js:250 Uncaught ReferenceError: Line is not defined at App.js:250
index.html:10 Uncaught TypeError: App is not a constructor at index.html:10
What am I doing wrong here?
Note
I also raised this issue on Github.

Copying the answer from GitHub:
svelte-cli works on individual files — you would need to compile Line.html separately, and include it on the page like so:
<!doctype html>
<html>
<head>
<title>My first Svelte app</title>
</head>
<body>
<main></main>
<script src='Line.js'></script> <!-- one for each component! -->
<script src='App.js'></script>
<script>
const application = new App({
target: document.querySelector( 'main' ),
data: {
name: 'world'
}
});
</script>
</body>
</html>
It will guess that Line.js is defining a global variable called Line, which is how App.js is able to reference it — but it prefers that you're explicit about that, by using the --globals option.
Needless to say, this is a huge pain — it doesn't scale at all past a certain point. For that reason we recommend that you use a build tool with Svelte integrated. That way, you don't have to worry about juggling all the different imported files, and as a bonus Svelte is able to generate more compact code (because it can deduplicate some helper functions between components).
The easiest way to get started — and I keep meaning to write a very short blog post about this — is to click the 'download' button in the REPL. That will give you a basic project setup that you can get running with npm run dev and npm start. Under the hood it uses Rollup to create a bundle that can run in the browser.
Here's your test app running in the REPL. Notice that the way we use the <Line> component is by declaring it using components, and just writing it into the template, rather than manually instantiating it with oncreate.

Related

How do I nest this React component in another React component?

Kind of embarrassing, since I worked as a React developer for over a year. But the system was set up when I came in, and when I created new components I just followed the syntax for the existing components and everything worked. But trying to do even simple React stuff on my home system has been really challenging. I'm not sure the problem is in my syntax, but maybe in my javascript environment.
Here is a simple thing that works:
react-test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>react-test-2</title>
<script type="text/javascript" src="../jquery-1.3.2.min.js"></script>
<script src="https://unpkg.com/react#18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom#18/umd/react-dom.development.js" crossorigin></script>
<script src="React_Components/AAA.js"></script>
<script>
$(document).ready(function() {
const domContainer = document.querySelector('#react-container');
const root = ReactDOM.createRoot(domContainer);
root.render(React.createElement(AAA));
});
</script>
</head>
<body>
<div id="react-container"></div>
</body>
</html>
AAA.jsx
function AAA(){
return (<div>AAA</div>);
}
The .jsx files are in React_Components_JSX, which is watched by the Babel preprocessor, which makes analogous .js files in React_Components. When I navigate to the html page, it renders the expected "AAA" on the page.
Now I'm just trying to nest another component inside the AAA component. So I update the file AAA.jsx and create a file BBB.jsx, something like the following (although I have tried various syntaxes hoping to make this work). I am expecting to see a webpage that renders "AAABBB".
AAA.jsx
import BBB from '../React_Components_JSX/BBB.jsx';
function AAA(){
return (<div>AAA<BBB/></div>);
}
BBB.jsx
export default function BBB(){
return (<div>BBB</div>);
}
The main error I am getting is "Cannot use import statement outside a module". Which I know explains the problem, but I don't really understand what that means on a fundamental level, as far as how I have to set my application up.

Can I run index.html with React without npm start and npx create-react-app?

I am self-learning react and I am just confused about a lot of things.
I thought that if I add React to my index.html via a script like the below:-
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bill Details</title>
</head>
<body>
<div id="billTable"></div>
<script src="BillTable.js" type="text/javascript"></script> ------------- Problem Line 1
</script>
</body>
</html>
and this is my js file where I am trying to return react component
//BillTable.js
import React from "react";
import ReactDOM from "react-dom";
function BillTable() {
return <h1>HELLO TABLE</h1>;
}
ReactDOM.render(<BillTable/>, document.getElementById("billTable"));
when I try to open index.html directly in firefox or through express server I get the below error in console:-
Uncaught SyntaxError: import declarations may only appear at top level of a module.
I then got rid of this error by changing the script type in problem line 1 in index.html to
<script src="BillTable.js" type="text/babel"></script>
but then also my webpage is completely blank and even console is not showing any errors.
Please suggest how to solve this issue. I am right now trying to learn React with functional approach only, so if any changes are required to be done on the react side, please make them in the functional approach.
I don't think you have included the correct packages to handle React components and JSX yet. These packages react, react-dom, etc. are usually in a package.json and are required to tell the browser what tools will be used to run the code. These packages handle the "script" or components you create and places the elements constructed in your components to the DOM. You can solve this by loading react with additional script tags before your component's script tag. This will let the browser know how and what to use to run your react component. Also, in your function, it does not know that it is a React Component. Check out an explanation for why you would have to use React.createElement I have attached an example of using only an index.html page here:
example of using an index.html page
Your Component file:
"use strict";
function BillTable() {
return React.createElement("h1", "", "HELLO TABLE");
}
const domContainer = document.querySelector("#billTable");
const root = ReactDOM.createRoot(domContainer);
root.render(React.createElement(BillTable));
and your index.html:
<body>
<div id="billTable"></div>
<!-- Load your React packages -->
<script
src="https://unpkg.com/react#18/umd/react.development.js"
crossorigin
></script>
<script
src="https://unpkg.com/react-dom#18/umd/react-dom.development.js"
crossorigin
></script>
<!-- Load your React component. -->
<script src="BillTable.js"></script>
</body>

import React Components to HTML

I'm trying to generalize my code by keeping a .js file containing only React components in one file and then utilizing these components in an HTML file. Here is my simple component:
component.js
'use strict'
class MyComponent extends React.Component {
render() {
return (
<div className="MyComponent">
<p>Text goes here.</p>
</div>
);
}
}
If in my component.js file I add: ReactDOM.render(<MyComponent/>, document.querySelector('#div-1')); and then, in my HTML, add <script src="component.js" type="text/jsx"></script> the React component shows in my page as expected.
However, my end goal is to be able to add the ReactDOM.render into my HTML within a script tag, that way I can have multiple pages utilizing the component.js components while doing all the assigning in the HTML page. Something like:
mypage.html (simplified)
<!DOCTYPE html>
<html>
<script src="component.js" type="text/jsx"></script> //import my components (no assigning done in this file)
<div id="div-1"><div>
<script>
ReactDOM.render(<MyComponent/>, document.querySelector('#div-1')); //assign to div
</script>
</html>
However this above code fails, with many errors regarding Uncaught SyntaxError: Unexpected token '<'
With that, how would I go about carrying something like this out? Any help is greatly appreciated.
The issue you're facing is that JSX isn't recognized by default in a browser.
Uncaught SyntaxError: Unexpected token '<' that's what this error means.
React docs have following help regarding that: quickly try JSX
you need to add babel in script tags and add type="text/babel" in whichever script you're using JSX.
<div id="counter_container"></div>
<!-- add babel support -->
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<!-- Load our React component. -->
<script src="components.js"></script>
<script type="text/babel">
(() => {
const Counter = window.Counter;
const counterContainerEl = document.querySelector('#counter_container');
ReactDOM.render(<Counter/>, counterContainerEl);
})();//this is just to avoid polluting global scope
</script>
I've put together a short example here github-repo

Does Vue not show in file #1 because of an unknown hidden character?

I expected both of these files to show 'Test!' and have a Vue component. Both of these files reference the exact same Vue source code. Both of these have what appear to be exactly the same Javascript. Both of these call the message key with the exact same mustache syntax.
Instead, one file shows me a {{ message }} while the other works as intended, showing Test!. Both files indicate that Vue is 'Ready. Detected Vue 2.5.21'. Here's the result of the 'broken' file. Why is there a difference?
I've tried (on the broken file):
Changing the CDN link where I get my Vue from (didn't work).
Changing the variable name that the Vue is stored in from 'root' to 'app' to 'rooty' (didn't work).
Using single parentheses vs. double for the ID and element reference (didn't work).
Changing the location of where the Vue source code is called, putting it at the top of the body and then beneath the content, as is default (nope).
(Vue staying alive despite deleting it). Deleting the Vue reference entirely to see if I was seeing a cached page (surprise! Even with the Vue reference gone, it still said 'Ready! Detected Vue 2.5.21').
Hard refreshing on Chrome to get rid of the cache with the Vue scripts deleted... still detected Vue.
Changing the file name to get a new, uncached version without Vue detected. (End the part where Vue stays alive after deleting it, i.e. Undead Vue).
Comparing the non-working script and the working script with https://www.diffchecker.com/diff (it showed the two files as exactly the same).
Copying the working script straight from Vue's documentation (how I made the working file, and it worked).
Retyping the Vue script again (this also got it to work).
Viewing the broken script on both Chrome (Version 70.0.3538.110 (Official Build) (64-bit)) and Firefox Quantum (65.0b4 (64-bit)). Both are still broken.
(Switching the coding context from Laravel Blade templates to a standalone HTML file; didn't work, so it was not Laravel's fault).
Using JS Fiddle to make sure it's not just my machine (it isn't; it did not work).
Environment:
Browsers mentioned above
PHP 7.2.11
PHP -S localhost:8001
Vue 2.5.21
Broken file:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
</head>
<body>
<h1>Home Page</h1>
<div id="rooty">
{{ message }}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var rooty = new Vue({
el: '#rooty',
data: {
message = 'Test!'
}
})
</script>
</body>
</html>
Working file:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Title</title>
</head>
<body>
<h1>Home Page</h1>
<div id="rooty">
{{ message }}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var rooty = new Vue({
el: '#rooty',
data: {
message: 'Test!'
}
})
</script>
</body>
</html>
Bibliography:
Learn Vue 2: Step By Step
Vue component not showing up
Simple html with vue.js not working
Introduction to Vue (Vue documentation)
The reason being a simple semicolon. On your broken file if you change = to : on the data it would work as expected.
var rooty = new Vue({
el: '#rooty',
data: {
message : 'Test!' //it is not message = 'Test!', but message: 'Test'
}
})
Here is your updated fiddle https://jsfiddle.net/jayas_godblessall/7e2g1ykd

The renderer for class sap.ui.core.mvc.View is not defined or does not define a render function! Rendering will be skipped! -

I am learning SAPUI5. In the link Plunkr. I have a few question.
I am trying to create a JS view and a controller to play with. Why do I have to specify my app, page inside getCore(). what if I would do it outside getCore(). But once I initialize app and Page inside my core method, console is throwing an error. Detail explanation will be really helpful. Thanks :)`
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
<script
id="sap-ui-bootstrap"
src= "https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"
></script>
<script src="script.js"></script>
</head>
<body>
<h1>Hello SAPUI5</h1>
<div class="sapUiBody" id="content"></div>
<div id="content1"></div>
</body>
// Code goes here
//debugger
sap.ui.getCore().attachInit(function(){
new sap.m.Text({
text:"Hello World, SAPUI5"
}).placeAt("content");
var app = new sap.m.App({
initialPage : "idViewDashboard1"
});
var page = new sap.ui.core.mvc.View({
id : "idViewDashboard1",
viewName:"ViewChartContainer",
type : sap.ui.core.mvc.ViewType.JS
});
app.addPage(page);
app.placeAt("content1");
});
`
The renderer for class sap.ui.core.mvc.View is not defined or does not define a render function! Rendering of idViewDashboard1 will be skipped! -
getCore() returns the Core instance which has the attachInit() event that
will either be called as soon as the framework has been initialized
or, if it has been initialized already, it will be called immediately.
Because things are loaded asynchronously, attachInit is the best place build your app with the ui5 framework because you can rely on that everything is available and ready.
Your plunkr emits that rather obscure error message because you create an empty instance of the class sap.ui.core.mvc.View that is meant to be abstract and indeed has no renderer method. To instantiate your view you should use the sap.ui.view() method:
var page = sap.ui.view({
id : "idViewDashboard1",
viewName:"viewChartContainer",
type : sap.ui.core.mvc.ViewType.JS
});
See here: https://plnkr.co/edit/ErToSaYgyg7KJ3HX52Oj?p=preview
If you want to learn UI5 i can recommend you to read the Walkthrough. There you can read about many more useful patterns other than that mentioned attachInit() like: encapsulate your app in a component, use XMLViews, use AMD-Modules,...

Categories