Nested Web Compontent render multipli - javascript

I just start building my first Web Compontent. I want to understand those frameworks out there and I start from scratch
MyProblem ist that the Components are rendering multipli times. So I have some parts more than once in a nested element.
An example will show you what is going wrong.
<html>
<head>
</head>
<body>
<wc-form>
<wc-box>
<wc-input></wc-input>
</wc-box>
</wc-form>
<script type="module">
import {Input} from './js/input.js';
import {Form} from './js/form.js';
import {Box} from './js/box.js';
</script>
</body>
</html>
Every Import i one of this Web Compontent I create like these one example
export class Form extends HTMLElement {
constructor() {
super()
}
render() {
this.innerHTML = `
<form style="border:5tpx solid green">
${this.innerHTML}
</form>`
}
}
window.customElements.define('wc-form', Form);
So I developed the slots function with the output from innerHTML. When I run this code I get nested boxes multipli because some parts are often rendered than ones. That is because I use the innerHTMl so so script always starts to render again and again.
When i do the import the right way as the elements can be strucred I don't get the Problem.

Related

I need to embed code in my Next.js site. (The next/script renders on all pages at the very bottom)

I feel like there should be a very simple solution to this and I can't seem to find one. I would like to embed code on my Next.js website, however, it will only work if I refresh the page. It does not load when I navigate to it via router/navbar link.
I tried to render it in useEffect() and useState(), however, the <script> doesn't seem to want to run in the useEffect() hook. I have not found a successful way to get dirty with it and use vanilla JavaScript in getServerSideProps() as suggested in another post, but I did find next/script in the documentation. This actually treats the script mostly how I need it to as far as when it renders. There is only one issue...
It does not render in the location I put it in the DOM. Instead it renders at the bottom of the webpage (even below the footer). I tried creating a component and then inserting it but that did not work either. This is because not only is it at the bottom of the current page, it's loading at the bottom of every page.
Any help is appreciated. Thank you!
Embedded component:
import Script from "next/script";
export default function paintCalculator() {
return (
<Script
async
type="text/javascript"
id="paint-calculator-tool"
data-type="dotdash-tool"
data-vertical="thespruce"
src="https://www.thespruce.com/static/5.174.0/static/components/widgets/iframe-embed/embed.min.js?id=paint-calculator-tool"
strategy="afterInteractive"
dangerouslySetInnerHTML={{
__html: `!function(){var e,i,n,a,t=document.getElementsByTagName("script");[].forEach.call(t,function(t){"dotdash-tool"===t.getAttribute("data-type")&&(e=t.parentElement,i=document.createElement("iframe"),n=t.getAttribute("id"),a=t.getAttribute("data-vertical"),i.src="https://www."+a+".com/tools/"+n,i.style.border="none",i.id=n,i.style.width="100%",t.nextSibling&&t.nextSibling.id===n||e.insertBefore(i,t.nextSibling))}),window.addEventListener("message",function(e){var t=document.getElementsByTagName("iframe");[].forEach.call(t,function(t){t.getAttribute("id")===e.data.embedId&&(t.style.height=e.data.height+10+"px")})},!1)}();`,
}}
/>
);
}
Page with imported component:
import styles from "../styles/Home.module.css";
import React from "react";
import PaintCalculator from "../components/PaintCalculator";
export default function paintCalculator() {
return (
<div className={styles.pageContainer}>
<div>
<h1>Paint Calculator</h1>
<PaintCalculator />
</div>
</div>
);
}

Render ReactJS app on demand by calling a JS function

I am wondering if it's possible to initialize react app in same way as a for example a jQuery component, since we need to create some widget with some options that would be so much easier in react than in pure JS/jQuery.
I have tried to wrap render(...) in a window.MyInitFunction = function ({....}) {render(<App />} then calling it in html, but it's undefined.
My goal is for example calling function
MyInitFunction({'selector': '.foo', 'someOtherProp': 'bar'});
and it will render the react app in the given selector which might be one or multiple elements.
I guess that there might be few problems if rendered to multiple elements since it will use the same js code for storing for example redux state,...
Goal is also to create a jQuery compatible extension from it in form of: $(".foo").MyInitFunction({.....});
Tried to google it, but nearly all results are irrelevant to what I want to achieve, mostly dynamically loading components, which is not my case.
$(".foo").MyInitFunction({.....});
Thank you in advance for any tips :)
You should be able to render a React app conditionally when you want. Check the snippet below. It renders the react app on click of the button.
// React Component
function App() {
return (
<div className="App">
<h1>Hello from React!</h1>
</div>
);
}
function renderReactApp() {
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById("root")
);
}
function init() {
document.getElementById("start").addEventListener("click", function() {
renderReactApp();
});
}
init();
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<body>
<button id="start">render react app from outside</button>
<div id="root"></div>
</body>

Why local browser won't show anything?

i have start learning with reactjs and purely new.i have created a new app in react and wrote the following code in Blog.js:
import React,{Component} from 'react';
const blogBody=()=>{
return(
<div class="card">
<h2>TITLE HEADING</h2>
<h5>Written By Ali</h5>
<p>Some text..</p>
</div>
)
}
class Blog extends Component {
render() {
return (
<div>
<blogBody/>
</div>
);
}
}
export default Blog;
and my App.js is:
import React,{Component} from 'react';
import Blog from './Blog'
class App extends Component {
render() {
return (
<div className="container">
<Blog/>
</div>
);
}
}
export default App ;
when i execute npm start, it shows nothing. then when i go to developer tools it is saying under the tab
You need to enable JavaScript to run this app.
did i do anything wrong with my code or in any setting? but when i run he initial page after creating new app fresh, it is showing the react thing with enable src regular stuff.
where did i do wrong?
this is my first post....please let me know if i break any rules and please help..
Component names have to start with capital letters.
Since blogBody doesn't, it is treated as an unknown HTML element and just inserted into the DOM.

Using a product tour library with VueJS

I'm trying to setup a feature intro tutorial for my web app (like intro.js). I'm having trouble with intro.js with nothing happening (no error message or tour messages). I tried setting up the data attributes that intro.js uses and calling the tour start from the mounted function on App.vue, but no luck. I'm looking to see if anyone has experience with with libraries like this combined with VueJS.
Code from App.vue:
mounted: function() {
const introJS = require('intro.js')
introJS.introJs().start()
}
Inside of the same component in it's <template>:
<div class="card card-accent-info" v-if="!isLoading" data-intro="Test step here" data-step="1">
I also have the css loaded in App.vue:
#import "~intro.js/minified/introjs.min.css";
The problem might be the way you're importing the CSS from the <style> tag. To get the styles to apply properly, import the CSS in JavaScript:
<!-- MyComponent.vue -->
<script>
import "intro.js/minified/introjs.min.css";
export default {
mounted() {
const introJS = require("intro.js");
introJS.introJs().start();
}
};
</script>
demo

React | Multiple render

I just want to know if there is any way I can "draw" in my index.html multiple <div id = "x" /> <div id = "y" /> with REACT, i mean.. i have all my site on index.html with all my template, so i only need to use REACT on an specifics sections...
i tried this i didnt work
HTML
<div id="test" />
<div id="app" />
<script src="public/bundle.js" charset="utf-8"></script>
JSX
import React from 'react';
import {render} from 'react-dom';
class App extends React.Component {
render () {
return (<h1>App</h1>);
}
}
class Test extends React.Component {
render () {
return (<h1>Test</h1>);
}
}
render(<App/>, document.getElementById('app'));
render(<Test/>, document.getElementById('test'));
then when i load the page only prints the <h1>Test</h1>... why?
I created a JSFiddle to try a few things out here: http://jsfiddle.net/pof580fd/1/
I found out that by explicitly closing each of the <div> tags I could get it to work, i.e.:
<div id="test"></div>
<div id="app"></div>
I did a little research and it appears that as div is not one of the HTML5 "void elements" (Listed here: https://www.w3.org/TR/html5/syntax.html#void-elements) it is not self-closing and you must use </div>. See this SO question for more details: Are (non-void) self-closing tags valid in HTML5?
Possibly some browsers are lenient about this (I'm using Chrome 52 right now) - but React is not, it appears. The error message I see in the console is:
Uncaught Error: Invariant Violation: _registerComponent(...): Target container is not a DOM element.
(Make sure you're using the "dev" version of React to see these)
You can create a new component and call from that.
import App from "./App";
import Test from "./Test";
class Program extends React.Component {
render() {
<div>
<div id="app"><App /></div>
<div id="test"><Test /></div>
</div>
}
}
and then call
render(<Program />), document.getElementById('...'));
We created a framework to do this with great success.
Have a look at React Habitat.
With it you can just register components eg:
container.register('SomeReactComponent', SomeReactComponent);
Then they auto resolve in the dom via:
<div data-component="SomeReactComponent"></div>

Categories