Rails 6 and Vue component - javascript

I have an app in Vue, separately is working. But if I add it into Rails, I don't know how to create a component (I have many of them, using v-for). In my standalone code is
import { createApp } from 'vue'
import App from './App.vue'
import Bar from './components/Bar.vue';
const app = createApp(App);
app.component('light-bar', Bar);
app.mount("#light-bars");
But I am unable to create component like this in Rails javascript/packs/light_bar.js.
Please, how to create a component inside Rails javascripts? My light_bar.js looks like:
import Vue from 'vue'
import App from '../light-bars/app.vue'
import Bar from '../light-bars/components/Bar.vue'
document.addEventListener('DOMContentLoaded', () => {
const app = new Vue({
render: h => h(App),
components: {
'light-bar': Bar
}
}).$mount('#light-bars');
console.log(app);
});
I also tried to import and register the component in my app, like this
import Bar from './components/Bar.vue'
export default {
name: 'App',
data() {
return {
barsData: []
};
},
components: {
'light-bar': Bar
}
...
and template looks like this
<template>
<div class="container">
<h3>Úrovně osvětlení pro různé situace</h3>
<div class="row">
<light-bar
v-for="bar in barsData"
:key="bar.id"
:luxRange="bar.luxRange"
:luxRangeName="bar.luxRangeName"
:luxLevel="bar.luxLevel"
:compensation="bar.compensation"
></light-bar>
</div>
</div>
</template>
But no component appears. Any tips what I am doing wrong?

I figured it out. But it is a little bit strange, I registered the component on both places, in packs/light-bars.js and also in my app.
import Bar from './components/Bar.vue';
export default {
name: 'App',
data() {
return {
barsData: []
};
},
components: {
'light-bar': Bar
},
...
and
import Vue from 'vue'
import App from '../light-bars/app.vue'
import Bar from '../light-bars/components/Bar.vue'
document.addEventListener('DOMContentLoaded', () => {
const app = new Vue({
render: h => h(App),
components: {
'light-bar': Bar
}
}).$mount('#light-bars');
console.log(app);
});

Related

How to register a global directive in Vue for entire app

How can i register a Vue directive so it's available in all of my components of my Vue application? I'm using Vue 2
The docs say you can register global but where in my project do I add this Vue.directive(....)
src/directives/TestMe.js
import Vue from 'vue'
export default Vue.directive('test-me', {
inserted(el) {
el.style.backgroundColor = 'red'
},
})
src/components/SignInForm.vue
<template>
<div>
<code v-test-me>
Hello World
</code>
</div>
</template>
</script>
I know the current way of doing this by doing the following. However it's not practical if I plan on using my directive in multiple components and pages of my application.
<template>
<div>
<code v-test-me>
Hello World
</code>
</div>
</template>
<script>
import TestMe from '../../directives/TestMe'
export default {
directives: {
TestMe
}
}
</script>
Updated
Updated post based on answers below.
I've created a different files for each directive and then have an index.js file where i import all my directives. How can i initiate that index.js file in the directives folder at the start of my application?
// src/directives/TestMe.js
export default testMe = {
inserted(el) {
el.style.backgroundColor = 'red'
},
}
// src/directives/index.js
import testMe from './TestMe'
export default {
install(Vue) {
Vue.directive('test-me', testMe)
// Vue.directive('other-directive', myOtherDirective)
},
}
// src/main.js
import Vue from 'vue'
import App from './App.vue'
import ???? from './directives'
const app = createApp(App)
app.use(????)
You have globalDirectives...where does that name come from?
EDIT: I didn't read that OP is using Vue 2.
To call .use(), you need to export object with function
install(Vue)
If you want the directive as a separate file.
// src/directives/TestMe.js
const testMe = {
inserted(el) {
el.style.backgroundColor = 'red'
},
}
export default testMe
Here is where you register all the directives. You can import files or just define your directives here.
// src/directives/index.js
import testMe from './TestMe'
// const myOtherDirective = {
// ...
// }
export default {
install (Vue) {
Vue.directive('test-me', testMe)
// Vue.directive('other-directive', myOtherDirective)
}
}
Here is how to register directives in Vue 2
You can register the global directives in main.js with Vue.use
// src/main.js
import Vue from 'vue'
import App from './App.vue'
import globalDirectives from './directives'
Vue.use(globalDirectives)
const app = new Vue({
router,
store,
render: h => h(App),
})
app.$mount('#app')
Here is how to register directives in Vue 3
You can register the global directives in main.js after createApp
// src/main.js
import Vue from 'vue'
import App from './App.vue'
import globalDirectives from './directives'
const app = createApp(App)
app.use(globalDirectives)

VueJS 3 Warn export compoment was not found in '#/components/...vue'

I'm using VueJS 3 applications using vue-router, vue and core-js applications where I want using compoments. I have in views dirrectory Home.vue file which looks like this:
<template>
<div class="wrapper">
<section v-for="(item, index) in items" :key="index" class="box">
<div class="infobox">
<PictureBox image="item.picture" />
<PropertyBox itemProperty="item.properties" />
</div>
</section>
</div>
</template>
<script>
import { ref } from 'vue'
import { data } from '#/data.js'
import { PictureBox } from '#/components/PictureBox.vue'
import { PropertyBox } from '#/components/PropertyBox.vue'
export default {
components: {
PictureBox,
PropertyBox,
},
methods: {
addRow() {
console.log('This add new row into table')
},
},
setup() {
const items = ref(data)
return {
items,
}
},
}
</script>
I have 2 compoments in compoments directory
src/compoments
|- PictureBox.vue
|- PropertyBox.vue
and for example in PictureBox.vue I have this content:
<template>
<div class="infobox-item-picturebox">
<img class="infobox-item-picturebox-image" :src="require(`#/static/${image}`)" alt="item.title" />
</div>
</template>
<script>
import { reactive, toRefs } from 'vue'
export default {
props: {
image: {
type: String,
},
},
setup() {
const state = reactive({
count: 0,
})
return {
...toRefs(state),
}
},
}
</script>
But I have Warning at compiling:
WARNING Compiled with 2 warnings 10:58:02 PM
warning in ./src/views/Home.vue?vue&type=script&lang=js
"export 'PictureBox' was not found in '#/components/PictureBox.vue'
warning in ./src/views/Home.vue?vue&type=script&lang=js
"export 'PropertyBox' was not found in '#/components/PropertyBox.vue'
App running at:
- Local: http://localhost:8080/
- Network: http://172.19.187.102:8080/
Also in Browser Developer mode I have same warnings:
My Directory structure looks like this:
And my main.js looks like here:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import './assets/style.css'
createApp(App).use(router).mount('#app')
And router page (I'm not using router actually looks like here)
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
})
export default router
Please, can you help me why I have this warning and my content from <template> in PictureBox or in PropertyBox was not loaded? Thank you so much for any advice
The component instance is exported as default (export default {...) in its single file and it should be imported like :
import PictureBox from '#/components/PictureBox.vue'
instead of:
import { PictureBox } from '#/components/PictureBox.vue'

Router not working when moving code into helper file

I tried to create some organization in my Vue app, so I moved my router confirguration to a separate file:
# /_helpers/router.js
import Vue from 'vue';
import VueRouter from 'vue-router';
import MemberDetail from '../MemberDetail';
import LoginPage from '../LoginPage';
Vue.use(VueRouter)
const routes = [
{ path: '/', component: MemberDetail },
{ path: '/login', component: LoginPage },
];
export const router = new VueRouter({routes});
router.beforeEach((to, from, next) => {
// redirect to login page if not logged in and trying to access a restricted page
const publicPages = ['/login'];
const authRequired = !publicPages.includes(to.path);
const loggedIn = localStorage.getItem('user');
if (authRequired && !loggedIn) {
return next('/login');
}
next();
})
Then I add the exported router in my main application.js:
import Vue from 'vue/dist/vue.esm'
import App from '../components/app.vue'
import { router } from '../components/_helpers';
document.addEventListener('DOMContentLoaded', () => {
new Vue({
el: '#app',
router,
render: h => h(App)
});
})
In my App.vue, I try to display the router-view:
<template>
<div class="page-container">
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'app'
};
</script>
<style scoped>
</style>
Unfortunataly this results in the following error:
[Vue warn]: Unknown custom element: <router-view> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
I don't understand what's wrong... I'm adding the router to the new Vue call, so I think it should be available.
Thanks

Vue.js component white screen

I got a white screen in my simple demo component and I have not any idea what is wrong with my code.
Dashboard.vue
<template>
<div id="app">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
msg: 'Hello'
}
}
}
</script>
main.js
import Vue from 'vue'
import Dashboard from './components/Dashboard.vue'
new Vue({
el: '#app',
components : {
Dashboard
}
})
Just white screen, components are not present in DOM. Vue2.X
Place this in your main.js, there's no render function in yours:
import Vue from "vue";
import Dashboard from "./components/Dashboard.vue";
Vue.config.productionTip = false;
new Vue({
render: h => h(Dashboard)
}).$mount("#app");

Adding corresponding JS file to a new Vue.js component

I'm learning Vue.js and it's been really awesome so far but I ran into a problem trying to add another JS file. I have a Navigation.vue file and I'm trying to add a new Vue instance to corrsponde with it, but I'm not having any success.
Navigation.js
new Vue({
el: '#navigation',
data: {
active: 'home'
},
methods: {
makeActive: function(item) {
this.active = item;
}
}
});
Navigation.vue
<template>
<div id="navigation">
<nav v-bind:class="active" v-on:click.prevent>
Home
Projects
Services
Contact
</nav>
</div>
</template>
<script>
export default {
}
</script>
Application.js
import Vue from "vue/dist/vue.esm"
import App from '../app.vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css';
Vue.use(Vuetify)
document.addEventListener('DOMContentLoaded', () => {
document.body.appendChild(document.createElement('app'))
const app = new Vue({
el: 'app',
template: '<App/>',
components: {
App
}
})
console.log(app)
})
The Navigation.js file isn't working. I think it's because I haven't imported it right, but I'm not sure?
ERROR:
Property or method "active" is not defined on the instance but
referenced during render. Make sure that this property is reactive,
either in the data option, or for class-based components, by
initializing the property
What I'd expect to see is your Navigation component included in your App component.
App.vue
<template>
<div>
<Navigation/>
<!-- there's probably more than just this -->
</div>
</template>
<script>
import Navigation from 'path/to/Navigation.vue'
export default {
// snip
components: {
Navigation
}
// snip
}
</script>
Also, component data should be a function
Navigation.vue
<script>
export default {
data () {
return { active: 'home' }
},
methods: {
makeActive (item) {
this.active = item;
}
}
}
</script>
There's no need to include Navigation.js or have a separate Vue instance for your Navigation component

Categories