How do I use PrimeVue in CustomElements? - css

I have a Vue 3 custom Element in which I want to use PrimeVue & PrimeFlex etc.
So I first create a Component, use the .ce.vue extension for the sfc mode and use the combination of defineCustomElement and customElements.define to compile it to a web component. Finally I use it in the index.html to see if it works in the Browser.
It works to some extent but not completely. For example, I am unsure about how to translate app.use(PrimeVue) for my case.
//customElement.ce.vue
<template>
<div>Test</div>
<AutoComplete field="name" />
</template>
<script lang="ts">
import { defineComponent } from "vue";
import AutoComplete from "primevue/autocomplete";
export default defineComponent({
name: "customElement",
props: {
msg: String,
},
components: { AutoComplete },
setup: () => {
console.log(JSON.stringify(theme));
return { PrimeVue };
},
styles: [],
});
</script>
<style scoped lang="scss"></style>
//main.ts
import { createApp, defineCustomElement } from "vue";
import App from "./App.vue";
//PrimeVue
import PrimeVue from "primevue/config";
import "/node_modules/primeflex/primeflex.css";
import "primevue/resources/primevue.min.css";
import "primevue/resources/themes/saga-blue/theme.css";
//CustomElement
import customElement from "#/components/customElement.ce.vue";
const customElementWC = defineCustomElement(customElement);
customElements.define("custom-element", customElementWC);
//Setup VueApplication for testing/reference, this works as expected.
const app = createApp(App);
app.use(PrimeVue);
app.mount("#app");
//index.html (for testing)
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript>
<div id="app"></div> //test app
<custom-element /> //the custom Web Component
<!-- built files will be auto injected -->
</body>
</html>
So I can see that the PrimeVue-Autocomplete is being shown, but the styles are not working.
So the question is:
How can I use all of PrimeVue in a custom Component?
Or in other words: How do I setup a Vue 3 CustomElement with PrimeVue?

So I have found a workaround (not a proper solution).
The way to make most of it work is to import the styles and js/ts modules in the component(s) itself.
The main styles make the most sense to import in the root component of the web component.
The reason why it has to be there is, due to:
https://github.com/vuejs/vue-cli/issues/6033 and
https://github.com/vuejs/core/issues/4662
that web components can't use plugins, or at least I don't know how. In other words there is no app.use() method.
I still couldn't properly import primeflex so I had to use the cdn link. I think it is possible to use an internal import, and I will update the answer when I find out how.
To use a specific PrimeVue component, simply import and register it as the documentation describes.
<template>
<Button />
</template>
<script lang="ts">
import Button from "primevue/button";
import { defineComponent } from "vue";
export default defineComponent({
components: { Button },
});
</script>
<style>
#import url("https://unpkg.com/primeflex#3.1.0/primeflex.css");
</style>
<style lang="scss" src="#/assets/scss/globals.scss"></style>
<style src="primevue/resources/primevue.min.css"></style>
<style src="primevue/resources/themes/tailwind-light/theme.css"></style>
//main.ts
import { defineCustomElement } from "vue";
import App from "./App.ce.vue";
customElements.define("custom-element", defineCustomElement(App));
Limitation:
Due to the missing plugin support (or my lack of knowledge of it) the lines:
import PrimeVue from 'primevue/config';
app.use(PrimeVue);
are not possible. Unfortunately, I can't fully grasp the impact that might have.

Related

Tailwind classes not getting applied for Astro Layouts

I am using Astro Tailwind integration, and I am trying to add some tailwind classes to MainLayout.astro which resides in layouts directory as follows
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
<main class="mx-20 mb-20 md:mb-28 xl:container xl:mx-auto">
<slot />
</main>
</body>
</html>
But styles are not getting applied to the <main> tag (according to browser dev tools inspection), but styles to the rest of the pages are getting applied.
What I have tried?
Restarting the dev server
Edit:
tailwind.config.cjs look like below
/** #type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
...
};
Edit 2:
astro.config.mjs
import { defineConfig } from "astro/config";
import react from "#astrojs/react";
import image from "#astrojs/image";
import tailwind from "#astrojs/tailwind";
// https://astro.build/config
export default defineConfig({
integrations: [
react(),
tailwind(),
image({
serviceEntryPoint: "#astrojs/image/sharp",
}),
],
});

Uncaught TypeError: Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript. at Object.jQueryDetection

I am using Next.js App and trying to add jquery in the application but the issue is sometimes it work sometimes not, I already added it to top of the script.
import React from 'react';
import Head from 'next/head'
import Script from 'next/script';
const LoadCss = () => {
return ( <>
<Head>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"/>
</Head>
</>
);
}
export default LoadCss;
import React from 'react';
import Script from 'next/script';
const LoadJs = () => {
return ( <>
<Script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></Script>
<Script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></Script>
<Script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></Script>
</> );
}
export default LoadJs ;
and rest are loaded after this but still facing the issue.
I also try to load it via local folder but still no success.
Kinldy help

next.js _document.js didn't get called

I have a small problem with next.js _document.js. I want to support Arabic, so, I add lang="ar" to Html component. But, in the page rendered there is no lang attribute in HTML. Hope somebody help me.
In order for Next.js to show updates made in _document you must stop and restart Next.js.
You must restart Next.js after making changes in _document, *.env, or any Next.js config files.
pages/_document.{ jsx | tsx }
import NextDocument, { Head, Html, Main, NextScript } from 'next/document';
class Document extends NextDocument {
render = () => (
<Html lang="ar" dir="rtl">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
export default Document;

How do I include my company's global styles CDN (for dev use) using Webpack, within a Vue cli project?

I've tried importing via the entry file (main.js)...
import Vue from 'vue'
import App from '#/App'
import router from '#/router/router'
import store from '#/store/store'
import BootstrapVue from 'bootstrap-vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import { Popover } from 'bootstrap-vue/es/directives'
import 'https://mycompany/main.min.css'
Vue.use(BootstrapVue)
Vue.use(Popover)
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
store,
router,
template: '<App/>',
components: { App }
})
I've tried to find a place within webpack.base.config (externals or publicPath) via numerous posts online - but none answered my question enough to make it work...
The css file delivered over the CDN essentially uses (and thus overwrites) Bootstrap classes, so it needs to be injected into the after Bootstrap - can I do this with my current setup? Vue/Webpack.. or do i need a task runner like Gulp? It's not enough to inject the cdn once we've built the project and have dist files.. we need to see the style changes whilst dev's work on the project.
Is there an easier way than either of those 2 methods, and before anyone asks - no.. they won't make it an npm package due to privacy/security.
The easy way would be to just include it in your index.html after all other Styles.
Btw: you can publish private repos on npm.
One way to do it is directly handling the template used by HtmlWebpackPlugin.
First disable inject in build/webpack.prod.conf:
//...
new HtmlWebpackPlugin({
//...
inject: false,
//...
})
//...
And in your index.html:
<!DOCTYPE html>
<html>
<head>
<!-- ... -->
<% if (process.env.NODE_ENV === 'production') { %>
<% for (file of htmlWebpackPlugin.files.css) { %>
<link rel="stylesheet" href="<%= file %>">
<% } %>
<link rel="stylesheet" href="https://mycompany/main.min.css">
<% } %>
</head>
<body>
<!-- ... -->
<div id="app"></div>
<% if (process.env.NODE_ENV !== 'production') { %>
<!-- During development there's less of a problem with putting stylesheets in the body -->
<link rel="stylesheet" href="https://mycompany/main.min.css">
<% } else{ %>
<% for (file of htmlWebpackPlugin.files.js) { %>
<script src="<%= file %>" type="text/javascript"></script>
<% } %>
<% } %>
</body>
</html>
What this does is inserting the static files manually, so you can choose the order, in production. During development, the link is written in the body tag, as then there isn't much of an issue with keeping standards.

Meteor+React Error: Uncaught Invariant Violation: _registerComponent(...): Target container is not a DOM element

I am looking at LevelUpTuts Meteor+React for everybody series.
I am having " Uncaught Invariant Violation: _registerComponent(...): Target container is not a DOM element. " error but I don't know where the problem is.
client/Main.html
<head>
<title>myResolutions</title>
<meta charset="utf-8"/>
</head>
<body>
<div id="target-render"></div>
<script src="./App.js"></script
</body>
In my App.jsx
client/App.jsx
import React from 'react';
import ReactDOM from 'react-dom';
class App extends React.Component{
render() {
return (
<h1> Hello World </h1>
)
}
}
if(Meteor.isClient){
Meteor.startup(function(){
ReactDOM.render(<App />,document.getElementById("render-target"));
});
}
It looks like in the html you have the id as "target-render", and in the javascript you have the id as "render-target". They need to match.
I guess the problem is coming from this line:
It shouldn't be here.
and I highly recommend you to use official Meteor tutorials instead of anything else:
https://www.meteor.com/tutorials/react/creating-an-app
First of, you need to import Meteor, import { Meteor } from 'meteor/meteor'; and then you don't need to include <script src="./App.js"></script> in your html. Note you have a typo on that line, you didn't properly close the script tag

Resources