How to use native slots in react? - javascript

I'm trying to build a simple application with react and web components UI library.
This library uses named slots in order to populate areas in the component.
When trying to use a named slot like this in my template:
<div slot="app-content"></div>
The rendered output is without the slot: <div></div>
Minimal reproduction:
Just add <div slot="mySlot" id="mySlottedDiv"></div> to a react component's template. Then inspect the resulting HTML and see that the slot attribute is omitted.
Here's an example of such an app: https://codesandbox.io/s/vivid-spring-hack-react-example-forked-yu9dss?file=/index.js
In this file, you can see I'm setting a div with slot="app-content" but the resulting HTML removes the attribute from the div - hence preventing me from using the web component's API.
Is there a way to force react NOT to remove attributes from an element? Is this a bug in react?

It seems like there are some issues opened and closed on some libraries trying to integrate with react to support slot attribute properly.
This seems to be a solution that circumvents react whitelisted attributes:
function slot(name = "") {
return { ref: (e) => e.setAttribute("slot", name) };
}
and then render:
<div {...slot("app-content")}>
This seems to work.
Here there are some more info: https://github.com/skatejs/skatejs/issues/1096
https://codesandbox.io/s/vivid-spring-hack-react-example-forked-nik1hs?file=/index.js

Ok, apparently this is working in react version 16 and above. Here's the blog post that explains that:
https://reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html
In my case, it is solved by upgrading react.

Related

How to add recharts to react-pdf

I am using 'recharts' to create graphs for my project,
and 'react-pdf' for generating a report.
'Recharts' creates a svg on the DOM when using it and a graph is displayed.
Is there a way I can use these two together, and add my 'recharts' component to my report via react-pdf?
for example - inside a <Document/> tag.
react-pdf link to website
recharts link to website
I have seen a solution which offers to convert the rechart's svg to a png, save it locally and then import it and use via <Image/> component in react-pdf.
Looking for a more straightforward approach to this issue.
Here is how I solved it :
I have used this article -
https://betterprogramming.pub/heres-why-i-m-replacing-html2canvas-with-html-to-image-in-our-react-app-d8da0b85eadf
It recommends using html-to-image package.
So I've given an id to the container of the rechart component,
and selected it with docoument.getElementById().
Then, used the selected id when querying html-to-image, like so -
const response = await htmlToImage.toPng(myId);
The response then contained a url,
which was used as an src for the react-pdf Image component.

Get HTML from Vuetify components without posting it on the dom

For my own project I would like to fetch HTML code from multiple Vuetify components. Not as a HTML string, but really as a DOM element that can immediately be appended to the body. I want this so that I can use these components in a non Vue environment.
Is there any way I can accomplish this?
I'm not entirely sure what your use case is for this. If you could elaborate on what you're trying to achieve, I could likely give a better answer.
I've had some similar requirement in the past, where I needed to access the entire HTML content of components/sub-components.
How I did this was by rendering the components in an iframe. From there, you can access and modify the mounted iframe DOM.
I can't find the source code on how I did this but perhaps concept/approach could serve as a starting point.
From a cursory internet search, I found this link https://jsfiddle.net/ohznser9/ with a JS Fiddle demonstrating a i-frame component that takes Vue components as a slot.
I'd imagine you could extend this component to add functionality to modify or extract elements from the DOM.
Perhaps you could load the iframe invisibly, grab the DOM elements from that and do what you wish with them

Custom Element is not working in IE 11 after transpiling

I have created a reusable web component and for this question's sake, let's call it <custom-el>. To invoke this custom element's implementation, I am writing it in my template files as following <custom-el class="container-for-custom-tag"></custom-el> and in the component, I am adding the children to this tag. When the browser engine finds out this tag, my component gets invoked and it adds children to this tag.
To make it work in IE 11, I have used document-register-element polyfill and it transpiles the file successfully. I don't get any errors in IE 11 when I load this transpiled file. But since the tag is also not recognized in IE11, nothing renders in UI. What am I doing wrong here?
I tried using babel plugins as well, I get the same result. The file gets transpiled but nothing renders in UI because of the tag.
Now, I have a solution in mind to invoke the web component on demand instead of it getting invoked because of the HTML tag. But I really want to know is there anything else which can be done to solve it. I saw on GitHub page of document-register-element that they have also put the custom tag in the HTML page in the examples but how is it working for them that I am not sure of.
This is how I am defining my custom Element:
class CustomEl extends HTMLElement {
// Inside this I render the child elements
// This HTML gets appended to the custom-el as children:
//<div class="text-container">20</div>
// I m not using shadow root
}
// Here I define the custom element
customElements.define('custom-el', CustomEl);
This is how I have invoked it:
// The following code goes in the template HTML file
<div class=“wrapper-container”>
<custom-el id="js-custom-el-conatiner”></custom-el>
<div>
When I load it in the browser, I get the following output in the browser inspector:
<div class=“wrapper-container”>
<custom-el id="js-custom-el-conatiner” >
<div class="text-container">20</div>
</custom-el>
<div>
For IE, I have required polyfill/document-register-elementin this file as per the github page documentation. class CustomEl extends HTMLElement gets compiled and I don't get any syntax error or any kind of error in the file. But since the HTML tag is still <custom-el> which invokes the implementation, it doesn't get invoked because that element is not recognized by IE browser engine.
It's not JS issue here - you have proved the custom element does its job and makes it into DOM. Now, make sure you have applied CSS to that element, basically telling browser how to render it. Start with basic display property. Without JSFiddle or CodePen or anything to play with it's hard to tell you the exact issue. Most of the times it's the problem to get a custom element into IE11 due to the fact it does not support ES6 constructs that are needed and one has to rely on polyfills like https://github.com/webcomponents/polyfills/tree/master/packages/webcomponentsjs

In Vue.js how can I know that the entire view has rendered, including AJAX calls?

According to the Vue.js API documentation using nextTick() inside mounted() will guarantee that the entire view has rendered, but I am not sure what they mean by "rendered" in this case.
I am trying to integrate the intro.js library intro Vue.js, but if I use put introJs().start() inside of nextTick like the following:
mounted: function () {
this.$nextTick(function () {
// Code that supposedly will run only after the
// entire view has been rendered
introJs().start()
})
}
it seems like the DOM is still not fully ready and introJs fails to show all intro steps successfully.
Reproduction link
How can I know that everything is truly ready? Is there any other way to start introJs within Vue.js?
The problem is that you are using v-if. If the condition is false, the html element will not be in document, meaning introjs can't find it. In the browser dev tools, if you look at the component when the v-if condition is false, you would see an html comment, <!-- -->.
The easy fix is to use v-show. This way the element will be in document, introjs can find it, and the user still won't see it because v-show toggles the display css property.

Material Design Lite JS not applied to dynamically loaded html file

I want to unify the navigation layout for my website, so I created a separate html file that holds the code for the navigation. I use a JS to load the file dynamically:
$("#navigation").load("/navigation/navigation.html", function() {
$.getScript('/material.min.js');
});
The problem is that the material.min.js does not get executed for the dynamically loaded components inside this html and I lose some crucial functionality. How do I fix that?
Check if the componentHandler is loaded, and try to upgrade the elements after load.
if(!(typeof(componentHandler) == 'undefined')){
componentHandler.upgradeAllRegistered();
}
How the Component Handler works
In short this goes over all registered components. Queries for all nodes with the provided CSS class. Loops over those and instantiates them one-by-one. When the upgrade is done on a node, the upgraded object is added to the dataset. This object contains a comma separated list of component classAsString properties to identify which upgrades have been done.
From the official docs:
Material Design Lite will automatically register and render all elements marked with MDL classes upon page load. However in the case where you are creating DOM elements dynamically you need to register new elements using the upgradeElement function.
So loading the material.js script again will not execute it. But you can do some experiments with upgradeElements by applying it to the whole loaded markup or to particular elements.

Categories