How to get $bvModal in setup? - vuejs3

I upgrading my Vue 2 project to Vue 3 (BootstrapVue (2.23.1) with #vue/compat). I facing serval problem. The first problem is how to get $bvModal in setup?
Anybody known?

import {BootstrapVue, BModal } from 'bootstrap-vue'import { createApp } from '#vue/compat' //In setup> const { BModal } = inject('BModal') //use> const $bvModal = new BModal({ ref: 'modal'})

Related

Importing vue-i18n in vuex module using quasar framework

My i18n boot file
import { boot } from 'quasar/wrappers';
import { LocalStorage } from 'quasar';
import messages from 'src/i18n';
import { createI18n } from 'vue-i18n';
const storedLang = LocalStorage.getItem('anty-locale');
const i18n = createI18n({
locale: storedLang && storedLang === 'en' ? 'en-US' : 'ru-RU',
messages,
});
export default boot(({ app }) => {
app.use(i18n);
});
export { i18n };
when I am trying to import in vuex js file like this
import { useI18n } from 'vue-i18n';
const { t } = useI18n({ useScope: 'global' });
I occur an error SyntaxError: Must be called at the top of a setup function
import i18n from 'boot/i18n';
i18n.t('common.user') //also doesn't work
Is there any correct way to import i18n in .js/.ts file?
I fixed like this and it worked.
import { i18n } from 'boot/i18n';
i18n.global.t('common.user'); // it works

Vue 3 extends vue.js components from third party library in defineComponent

I want to use third party library element-plus in my component. In setup defineComponent entends that component. In console, it would warn Failed to resolve component: el-radio at <App>
In about router, Here is the about.vue
<template>
<div id="popup-content"></div>
</template>
<script>
import {
onMounted, createApp, defineComponent, nextTick,
} from 'vue';
import Test from '#/components/Test.vue';
export default {
setup() {
onMounted(() => {
const myNewComponent = defineComponent({
extends: Test,
});
createApp(myNewComponent).mount('#popup-content');
nextTick(() => {
createApp(myNewComponent).mount('#popup-content');
});
});
},
}
Test component has used element-plus el-raido component, Test.vue
<template>
<el-radio v-model="radio" label="1">备选项</el-radio>
<el-radio v-model="radio" label="2">备选项</el-radio>
</template>
<script>
export default {
data() {
return {
radio: '1',
};
},
};
</script>
I have add element-plus, and register all in main.js
import { createApp } from 'vue';
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
import App from './App.vue';
const app = createApp(App);
app.use(ElementPlus);
app.mount('#app');
I have found this question
Extend vue.js component from third-party library
I really really don't understand what are you trying to achieve by extending your perfectly fine Test component BUT...
Vue 3 is very different from Vue 2 - a lot of global API's (as component registration for example) are not global anymore but are tight to a "app instance" (created by createApp)
So even if you register Element components in main.js (app.use(ElementPlus);), the another app instance (why!?) created in onMounted hook of about.vue component knows nothing about the components! That is the reason for an error...
You must register components in every app instance created by createApp you want to use them in ....
As #Michal Levý answered, I need to register components in every app instance created by createApp.
Here is the working version about.vue, in case someone need.
<template>
<div id="popup-content"></div>
</template>
<script>
import {
onMounted, createApp, defineComponent, nextTick,
} from 'vue';
import Test from '#/components/Test.vue';
import ElementPlus from 'element-plus';
import 'element-plus/lib/theme-chalk/index.css';
export default {
setup() {
onMounted(() => {
const myNewComponent = defineComponent({
extends: Test,
});
const app1 = createApp(myNewComponent);
nextTick(() => {
app1.use(ElementPlus);
app1.mount('#popup-content');
});
});
},
}

Meteor 1.5 : Dynamic Import for Blaze

I am having two questions:
1) I want to use Meteor 1.5 Dynamic Import for Blaze but all the examples and tutorials are given for React. So I am confused how exactly it can be used . Can anyone give examples of it.
2) I am using packages from atmospherejs.com like amcharts which I only need at Admin Dashboard side. How to dynamically import them?
Thanks in Advance!
UPDATE(Solution):
Below is homepage.html (parent template)
<template name="homepage">
Homepage Content
{{> Template.dynamic template=content}}
</template>
login.html (child template)
<template name="login">
You're logged in!
</template>
login.js
import '../homepage/homepage.js';
import './login.html';
API = function () {
BlazeLayout.render("homepage",{content: 'login'});
}
export { API }
main.js
LoadLogin = function () {
import('/imports/modules/common/login/login.js').then(function (api) {
api.API();
})
}
/lib/route.js
import { FlowRouter } from 'meteor/ostrio:flow-router-extra';
FlowRouter.route('/', {
name: 'homepage',
action() {
LoadLogin();
}
});
I am developing my own admin panel, Meteor Candy, to be driven by dynamic imports, so I am happy to share how I got it working.
First, we have the view.html:
<template name="admin">
Admin
</template>
Second, we have our JS logic:
import { Template } from 'meteor/templating';
import { Meteor } from 'meteor/meteor';
import { Blaze } from 'meteor/blaze';
import './view.html';
API = {}
API.render = function () {
Blaze.render(Template.admin, document.body);
}
export { API }
Finally, we just need to import that code and trigger our Template to be rendered into the page:
openAdmin = function () {
import('./imports/admins').then(function (api) {
api.render()
})
}
Once something runs the openAdmin() function, the templates will be imported from the server and the render function will be called.
The basic technique for dynamically importing modules in Meteor 1.5 using Blaze is as follows:
Template.theTemplate.events({
'click button'(event, instance) {
import("foo").then(Foo => {
console.log(Foo);
});
}
});
Make sure you take a close look at how your module is then imported, because apparently some refactoring may be needed when calling it in your code. For example, using "zxcvbn":
WAS
const result = zxcvbn(pwd);
IS
const result = zxcvbn.default(pwd);
It is pretty straight forward using example link https://github.com/thesaucecode/meteor-amcharts-example/blob/master/client/example2.js, you just have to write the code inside Template.MYTEMPLATE.onRendered(function(){});
On top of that you can use var chart as reactive-var.

How do I pass Meteor Subscription Data into React Component Props using ES6

Given this subscription, and the React Component below, how do I pass the subscription data in as props 'searchTerms'? Most of the documentation I can find refers to using mixins, but as far as I understand this is an anti pattern in ES6. Thanks!
constructor() {
super();
this.state = {
subscription: {
searchResult: Meteor.subscribe("search", searchValue)
}
}
}
render() {
return (
<div>
<SearchWrapper
searchTerms={this.state.subscription.searchResult}
/>
</div>
)
}
There are a couple options when it comes to creating containers in Meteor. My personal favorite is react-komposer.
Here's what your container would look like using react-komposer. Note that a container is simply a component that just passes data, and in the case of Meteor, provides reactivity.
After npm install --save react-komposer, create a container using:
import { Meteor } from 'meteor/meteor';
import React from 'react';
import { composeWithTracker } from 'react-komposer';
import Component from '../components/Component.jsx';
import { Collection } from '../../api/collection/collection.js';
// Creates a container composer with necessary data for component
const composer = ( props, onData ) => {
const subscription = Meteor.subscribe('Collection.list');
if (subscription.ready()) {
const collection = Collection.find().fetch(); // must use fetch
onData(null, {collection});
}
};
// Creates the container component and links to Meteor Tracker
export default composeWithTracker(composer)(Component);
The standard way of doing this is to use the react-meteor-data package.
meteor add react-meteor-data
Then create a container as follows:
import { Meteor } from 'meteor/meteor';
import { createContainer } from 'meteor/react-meteor-data';
import SearchWrapper from '../pages/SearchWrapper.jsx';
import { SearchResults } from '../../api/searchResults.js';
export default SearchResultContainer = createContainer(({ params }) => {
const { searchValue } = params;
const searchHandle = Meteor.subscribe('search', searchValue);
const loading = !searchHandleHandle.ready();
const results = SearchResults.find().fetch();
const resultsExist = !loading && !!list;
return {
loading,
results,
resultsExist,
};
}, SearchWrapper);
The returned object from the container is available as props in the wrapped component - SearchWrapper.

Unexpected browserHistory behaviour (Meteor + React + React Router)

(PS: I'm using Meteor + React + React Router. The application structure is not traditional, I'm making a package-esq application, an example is https://github.com/TelescopeJS/Telescope. I'm trying to do dynamic routing with react router and things are not working out well.)
There be something wrong with browserHistory. Navigation refreshes the page. Going back and forth through the browser buttons refreshes the page.
Example of this, with all codes, are here - https://github.com/dbx834/sandbox
React-Router specific codes follow,
In a core package, with a global export, allow registeration of routes and components
...
// ------------------------------------- Components -------------------------------- //
Sandbox.components = {};
Sandbox.registerComponent = (name, component) => {
Sandbox.components[name] = component;
};
Sandbox.getComponent = (name) => {
return Sandbox.components[name];
};
// ------------------------------------- Routes -------------------------------- //
Sandbox.routes = {};
Sandbox.routes.routes = [];
Sandbox.routes = {
routes: [],
add(routeOrRouteArray) {
const addedRoutes = Array.isArray(routeOrRouteArray) ? routeOrRouteArray : [routeOrRouteArray];
this.routes = this.routes.concat(addedRoutes);
},
};
...
In various implementations (domain specific logic, UI, etc), register components and routes
...
import TodoApp from './components/TodoApp.jsx';
Sandbox.registerComponent('TodoApp', TodoApp);
Sandbox.routes.add([
{ name: 'todoAppRoute', path: 'todo-app', component: Sandbox.components.TodoApp },
]);
...
In the main app
import React from 'react';
import { render } from 'react-dom';
import { Meteor } from 'meteor/meteor';
import { Router, browserHistory } from 'react-router';
import App from './components/App.jsx';
import Homepage from './components/Homepage.jsx';
Sandbox.registerComponent('App', App);
Sandbox.registerComponent('Homepage', Homepage);
Meteor.startup(() => {
const AppRoutes = {
path: '/',
component: Sandbox.components.App,
indexRoute: { name: 'home', component: Sandbox.components.Homepage },
childRoutes: Sandbox.routes.routes,
};
console.log(AppRoutes);
render(
<Router routes={AppRoutes} history={browserHistory} />,
document.getElementById('app-root')
);
});
What is wrong?
I uninstalled all npm packages, meteor packages, updated everything, re-installed latest packages, cleaned out all previous builds and everything works now!
There was something weird somewhere.
If anyone finds themselves in a similar situation, you can try this.
Best

Resources