Does Lit have mounted lifecycle like Vue? - blockly

My Vue app did set up a Blockly element in mounted. I'm updating the app by using Lit. In connectedCallback the target element which hosts Blockly is not contained in the document.
connectedCallback(): void {
super.connectedCallback()
const editorDiv = this.renderRoot.querySelector('#visual-editor-div')
Blockly.inject(editorDiv)
}
render() {
return html`
<div id="visual-editor-div"></div>
`
}
Error message was:
Error: container is not in current document.
Is there the way to inject Blockly after container mounted in Lit?

Related

"Maximum call stack size exceeded" when using Vue.component

This is a very weird one.
I have some HTML retrieved from a headless CMS, via the asyncData hook, and which I'm displaying via a dynamic component, as follows (truncated for brevity):
<script>
import {apiReq} from '~/assets/js/utils'
import Vue from 'vue'
export default {
data() { return {
}},
async asyncData(ctx) {
let req = await apiReq.call(ctx, 'getMeta', {uri: ctx.route.params.article}, true);
if (req === null) return;
let contentComp = Vue.component('test', {template: '<div>'+req.data.content+'</div>'})
return {article: req.data, contentComp}
},
methods: {}
}
</script>
...and rendered in my template via:
<component :is='contentComp'></component>
I'm using a dynamic component rather than simply v-html because the fetched HTML contains references to child components that should be rendered.
The above results in a "maximum call stack size exceeded" error. If I kill the JS line that creates the dynamic component (Vue.component(...) everything's fine and the page loads. There's no issue with the API request - that fetches the data just fine, with a 200.
The error persists if I keep the JS line but remove the <component... rendering line, so it seems the error is emanating from the creation of the dynamic component, not its rendering.
This happens both with target set to 'server' and 'static'.
[ UPDATE ]
req.data.content is the string of markdown coming from the CMS, which also contains some child component references.

Bind dynamic Vue image src from node_modules

I' am creating a Vue component that shows an SVG image from my node modules based on a given image name or key (given by an API).
If I put the source image directly like ~cryptocurrency-icons/svg/color/eur.svg, the resource loads.
But if I try to compute it with the props or by the mounted method asigning it using :src="imageSource" it does not load.
I'm new to Vue so I don't know why is this happening? Should I use images downloaded in a public directory instead of the NPM package?
<template lang="html">
<img src="~cryptocurrency-icons/svg/color/eur.svg" alt="icon" />
</template>
<script lang="js">
export default {
name: 'crypto-icon',
props: ['currency'],
mounted() {
this.imageSource = `~cryptocurrency-icons/svg/color/${this.currency}.svg`
},
data() {
return {
imageSource: ""
}
},
methods: {
getImageResource(){
return `~cryptocurrency-icons/svg/color/${this.currency}.svg`
}
},
computed: {
}
}
</script>
<style lang="scss" scoped>
.crypto-icon {}
</style>
You are missing the require attribute. Vue Loader, does this automatically when it compiles the <template> blocks in single file components. Try with this:
require(`~cryptocurrency-icons/svg/color/${this.currency}.svg`)
You can read more here.
I've solved it by using a Vue plugin (see vue-cryptoicons), although hatef is right about using require for image resources, using it in directories under node_modules tries to find the full path
~cryptocurrency-icons/svg/color in ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"a7e19d86-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Wallet.vue?vue&type=template&id=7f1455a9&scoped=true&lang=html&
To install it, you can run: npm install --save ~cryptocurrency-icons/svg/color

LitElement <slot> not wokring

I'm creating my custom accordion element. In which I'll have 2 components 1 for ul and other for li.
Content in file accordion-ul.ts, in which I've a slot where I want my li.
import { html, customElement, property, LitElement } from 'lit-element';
import { Accordion } from 'carbon-components';
#customElement('accordion-panel')
export default class AccordionPanel extends LitElement {
firstUpdated() {
const accordionElement = document.getElementById('accordion');
Accordion.create(accordionElement);
}
connectedCallback() {
super.connectedCallback();
}
render() {
return html`
<ul data-accordion class="accordion" id="accordion">
<slot></slot>
</ul>
`;
}
createRenderRoot() {
return this;
}
}
NOTE: I'm getting an error in the console in the firstUpdated() : Uncaught (in promise) TypeError: Cannot read property 'nodeName' of null.
The way I'm using it for testing:
<accordion-panel><li>test</li></accordion-panel>
IDK, it's not working and nothing is printing on the screen. On inspecting the element, I can see there's empty in DOM.
Your problem is that you're trying to use slots, which are a shadow DOM feature but you're not using shadow DOM (since you're overwriting the createRenderRoot method to prevent the creation of the shadowRoot)
So, if you want to use slots, just remove the createRenderRoot function from your class and use shadow DOM
Edit:
You should also update your firstUpdated method so that this part:
const accordionElement = document.getElementById('accordion');
Uses the element from your shadow DOM
const accordionElement = this.shadowRoot.querySelector('.accordion');
Then again, CarbonComponents styling will probably not work so you'll need to add those in some other way

Importing an image into an <src> tag in React.js when the image name is not known in advance

I have a component in React which displays (or doesn't at the moment) an image within an src tag.
The file path & file name of the image is passed via props after being selected by the user, so I can't do an import at the top of the file. Apparently, I should be able to do something like src={require(file)} but this causes webpack to throw a hissy fit and give the following error: Error: cannot find module "."
As an e.g., a typical filepath/filename I pass to the component is: '../../../images/black.jpg'
This is a stripped-down version of the code in question:
import React, { Component } from "react";
class DisplayMedia extends Component {
render() {
return (
<div className="imgPreview">
<img src={this.props.file} alt="piccy" />
</div>
);
}
}
export default DisplayMedia;
Depending on your set up...
If the images are dynamic (during production, images will be added, edited, or deleted):
I'd recommend a microservice that only handles images. I go in depth on how to approach such a service: Image returned from REST API always displays broken
If the images are static (during production, the images are bundled within the "bundle.js" file):
- I'd recommend importing all of the images within the component, creating an array of the imported images, and then utilizing the array index and React state to cycle through them. For example:
import React, { Component } from "react";
import Image1 from "../images/Image1.png";
import Image2 from "../images/Image2.png";
import Image3 from "../images/Image3.png";
const images = [Image1, Image2, Image3];
export default class ShowImage extends Component {
state = { index: 0 };
handleChange = ({ target: { value } }) => {
this.setState({ index: value });
};
render = () => (
<div className="container">
<h1>Utilizing Array Indexes</h1>
<select
style={{ marginBottom: 20 }}
value={this.state.index}
onChange={this.handleChange}
>
{images.map((val,idx) => (
<option key={idx} value={idx}>Image {idx + 1}</option>
))}
</select>
<img src={images[this.state.index]} />
</div>
);
}
While I can't create an exact codesandbox of the above, this working example should give you the basic idea: https://codesandbox.io/s/ovoo077685
You don't need to add require in src. When relative path is used it will go the images availale in your server but when url is given image will be loaded. You can find more info here
When using src as /images/black.jpg it will convert to localhost:3000/images/black.jpg

How to Trouble Shoot and Fix React.js Checksum Invalid Warning

I am building an Isomorphic react app using the Isomoprhic React Starter kit project here : https://github.com/kriasoft/react-starter-kit
However I am running into a mysterious warning that I have not figured out how to trouble shoot.
React appears to render the code fine in my browser, but apparently there is some problem with rendering on the server.
Here is the warning that I get:
warning.js:45Warning: React attempted to reuse markup in a container
but the checksum was invalid. This generally means that you are using
server rendering and the markup generated on the server was not what
the client was expecting. React injected new markup to compensate
which works but you have lost many of the benefits of server
rendering. Instead, figure out why the markup being generated is
different on the client or server:
and Here is the code from my component that is the source of the problem:
class TestPage extends React.Component {
constructor () {
super()
this.state = { n: 0 }
}
static contextTypes = {
onSetTitle: PropTypes.func.isRequired
};
static defaultProps = {
blahblah: 'blah'
}
render() {
let title = 'Test Page';
this.context.onSetTitle(title);
return (
<div className="page">
<div className="pageContainer">
<h1>{title}</h1>
{this.state.n}
<TestComponent blahblah={this.props.blahblah} />
</div>
</div>
);
}
}

Resources