Vue.js cannot use to <slot> to render the parent component - javascript

I just try to follow the example about the use of slot on the Vue official site. But it failed, I have made the code very short
parent component
<template>
<subMenuTemp>
<div class="text" >
parent content
</div>
</subMenuTemp>
</template>
<script>
import subMenuTemp from 'src/test/testChildren.vue'
export default {
data() {
},
components: {
subMenuTemp
}
}
</script>
children component another .vue file
<template>
<div class="content">
<slot>
old content
</slot>
</div>
</template>
<script>
export default {
}
</script>
although the code is very short, I still cannot find where is my fault

Make sure to include the two components in your main.js or some .js file that imports Vue. It should look like this:
import Vue from 'vue'
import App from './App'
import subMenuTemp from './test/testChildren.vue'
new Vue({
el: '#app',
template: '<App/>',
components: { App, subMenuTemp }
})

You don't need to register all components in the main file as pointed in other answers.
You just need to import the child component into the parent component just as you do.
See a here: https://codesandbox.io/s/vue-template-oy15j?fontsize=14
// App.vue
<template>
<div id="app">
<parent-component message="Hello Vue !"/>
</div>
</template>
<script>
import ParentComponent from "./components/ParentComponent";
export default {
name: "App",
components: { ParentComponent }
};
</script>
// ParentComponent.vue
<template>
<child-component>
<div class="test-parent">{{ message }}</div>
</child-component>
</template>
<script>
import ChildComponent from "./ChildComponent";
export default {
name: "ParentComponent",
components: { ChildComponent },
props: {
message: String
}
};
</script>
// ChildComponent.vue
<template>
<div class="test-child">
<slot>default content</slot>
</div>
</template>
<script>
export default {
name: "ChildComponent"
};
</script>
<!-- Result -->
<div id="app">
<div class="test-child">
<div class="test-parent">Hello Vue !</div>
</div>
</div>

Related

Using components on pages, layout always choosing default. Can not chose another layout

I have a problem of nuxt.js
When I try using components in some pages, and layout is 'something' (layout:'something').
But layout always applied default.
Is this a nuxt bug? or there some rules about it?
// pages/main.vue
<template>
<div>
<something />
</div>
</template>
<script>
import something from "#/components/something.vue";
export default {
components: {
something
},
layout: 'a'
};
</script>
.
.
.
// layouts/a.vue
<template>
<v-app class="dark">
<nuxt/>
</v-app>
</template>
<style scoped>
.dark {
background:black;
}
</style>
.
.
.
// components/something.vue
<template>
<div>
Hello
</div>
</template>
Add some paragraph to your layout and check out if its applied:
<template>
<v-app class="dark">
<p>Hello from layout</p>
<nuxt/>
</v-app>
</template>
Are you not suppose to import the v-app component to your layout and then export it?
<script>
import VApp from "#/components/../..
export default {
components: {
VApp
}
</script>
Of course, depending of the location of your v-app component

How to trigger a method in Single File Component from another Single File Component VueJS

I have Three components I want to trigger the show() method that is located in overlay.vue component, from the about.vue component
I am a beginner so I wish if I found some help from you guys
first is overlay.vue
<template>
<div class="overlay"></div>
</template>
<script>
export default {
name: "overlay",
methods: {
show() {
document.querySelector(".overlay").style.display = "block";
}
}
};
</script>
second is about.vue
<template>
<section class="about">
<div class="container">
<div class="row video">
<div class="col-lg-6 order-lg-1 order-2">
<img
class="dots img-fluid"
src="../assets/images/dots.svg"
alt="dots"
/>
<div class="video-wrapper">
<div class="video-img">
<img
class="img-fluid"
src="../assets/images/video.png"
alt="#"
/>
</div>
<div class="video-i">
<!-- ***************************************************************
***** this is where i want to trigger the method using this below a tag*****
*************************************************** -->
<i class="fas fa-play"></i>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
The third which is the parent app.vue where I import about.vue and overlay.vue
<template>
<div id="app">
<overlay></overlay>
<about></about>
</div>
</template>
<script>
import overlay from "./components/overlay";
import about from "./components/about";
export default {
name: "App",
components: {
about,
overlay
}
};
</script>
You can do something like this, in your app.vue set a variable to show your overlay.vue or not. And then in the overlay.vue set a props that change the style of your component. This solution is not using a dom manipulation.
app.vue
<template>
<div id="app">
<overlay :show="show_overlay"></overlay>
<about></about>
</div>
</template>
<script>
import overlay from "./components/overlay";
import about from "./components/about";
export default {
name: "App",
data(){
return {
show_overlay:false
}
},
components: {
about,
overlay
}
};
</script>
overlay.vue
<template>
<div class="overlay" :style="[(this.show) ? 'display:block' : 'display:none']"></div>
</template>
<script>
export default {
name: "overlay",
props:{
show:{
default:false,
type:Boolean
}
}
};
</script>
because the two components are siblings and not imported in each other I coulden't use $ref and the best choice is to use Store
this is my store code
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
showOverlay: false
},
mutations: {
//showing the overlay
TOGGLE_OVERLAY(state, payload) {
state.showOverlay = payload;
}
},
actions: {
//showing the overlay
toggleOverlay(context, payload) {
context.commit("TOGGLE_OVERLAY", payload);
}
},
getters: {
getStatus: state => state.showOverlay
}
});
and here where i dispatch it. I dispatch it from about.vue or any other component as well
<a #click.prevent="toggleOverlay" href="#"><i class="fas fa-play"></i></a>
methods: {
toggleOverlay() {
this.$store.state.showOverlay = !this.$store.state.showOverlay;
this.$store.dispatch(
"toggleOverlay",
this.$store.state.showOverlay
);
}
}

how to load vuejs component from laravel blade?

I'have multiple auth laravel dashboard. When i login the default page redirect me to the client dashboard blade. When i write something in client blade.It does not show anything.I am using vuejs routers. Everything is working perfect. I tried to call component in that blade but it's still showing blank .I want to redirect to dashboard component.
Controller:
I tried it with the return url('url here') but still not working for me.
public function index()
{
return view('client');
}
Client Blade:
#extends('layouts.master')
#section('content')
<template>
<div class="container-fluid">
<client_details></client_details>
</div>
</template>
<script>
import clientdetails_header from "./clientdetails_header.vue";
export default {
data() {
return {
}
},
components: {
'client_details': clientdetails_header
},
mounted() {
console.log('Component mounted.')
}
}
</script>
#endsection
Master Blade:
<ul>
<li>
<router-link to="/clientdashboard" title="dashboard">
<span class="nav-link-text"><iclass="fal fa-user"></i>DashBoard</span>
</router-link>
</li>
</ul>
<div class="page-wrapper" id="app">
<div class="page-content">
<router-view>
</router-view>
</div>
</div>
App.js
let routes = [
{path: '/clientdashboard', component: require('./components/clientdashboard.vue').default},
]
const app = new Vue({
el: '#app',
router,
});
const router = new VueRouter({
mode: "history",
routes
})
ClientHeader:
<template>
<div class="row">
<div class="col-xl-12">
<!-- Collapse -->
<div id="panel-6" class="panel">
<div class="panel-hdr">
<h2>
Client Details
</h2>
</div>
<div class="panel-container show">
<div class="panel-content">
<div class="row">
<div class="col-md-2">
<span><b>Company name:</b></span> <br>
<span><b>Company ABN:</b></span> <br>
<span><b>Company address:</b></span> <br>
<span><b>Company phone:</b></span> <br>
<span><b>Company email:</b></span> <br>
</div>
<div class="col-md-10">
<ul style="list-style: none;" class="list-group list-group-flush">
<li style="text-decoration: none" v-for="todo in clientData">{{todo}}</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
user_id: this.$userId,
clientData: {}
}
},
methods: {
getClientDetails() {
axios.post(this.$path + 'api/getClientDetails', null,
{
params: {
'client_id': this.user_id,
}
})
.then(data => (
this.clientData = data.data));
}
},
mounted() {
this.getClientDetails();
console.log('Component mounted.')
}
}
</script>
I don't think it's a good idea trying to put Vue code directly inside blade.
I would suggest you create a Client.vue and put your code in it instead. Register it in your routes in app.js.
...
{path: '/client', component: require('./components/Client.vue')},
Then you can use the component in your Client blade.
<client></client>
I believe that would be a first step towards resolving this issue.
Load your app.js in <head> section of your blade.php
<script src="{{ asset('js/app.js') }}" async></script>\
Also create a div with id app there.
<body>
<div id="app"></div>
</body>
Create App.vue
<template>
<div>
<router-view />
</div>
</template>
<style scoped lang="scss">
</style>
Go to resources/js/app.js file, you will see laravel already put code to instantiate vue in there. Register your route etc.
But for me, I create a new folder resources/js/vue, put all vue related files (components, routes, filters, vuex, mixins, directives) there, create index.js and moved the code to initiate vue inside index.js.
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'
import components from './components'
import directives from './directives'
import mixins from './mixins'
import filters from './filters'
Vue.use(router)
Vue.use(store)
Vue.use(components)
Vue.use(directives)
Vue.use(mixins)
Vue.use(filters)
new Vue({ router, store, render: h => h(App) }).$mount('#app')
export default {}
resources/js/app.js
require('./vue')
// I also initiate service-worker, firebase, and other non vue related
// javascripts in this file

Cannot find element in Vue Js Applications

I created vue js applications with visual studio 2017 . but the problem is when i run the applications , i got following errors in google chrome console windows .
[Vue warn]: Cannot find element: #intro
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
Here is the code for App.vue...
<template>
<div id="app">
<Home msg="Hello world!" />
</div>
</template>
<script>
import Home from './components/Home.vue';
import component1 from './components/component1.vue';
export default {
name: 'app',
components: {
Home,
component1
}
};
</script>
<style>
</style>
Here is the code for component1.vue..
<template>
<div class="intro" style="text-align:center;">
<h1>{{ message }}</h1>
</div>
</template>
<script type="text/javascript">
import Vue from 'vue';
new Vue({
el: '#intro',
data: {
message: 'My first VueJS Task'
}
});
</script>
<style scoped>
</style>
Here is the screen shot of the google console windows ..
You have set the class on the element instead of the id.
But that is irrelevant anyway because you do not need to any of this for a single file component; just do this instead (as you did for App.vue):
<template>
<div class="intro" style="text-align:center;">
<h1>{{ message }}</h1>
</div>
</template>
<script>
export default {
data() {
return {
message: 'My first VueJS Task'
}
}
}
</script>
Constructing a Vue component manually with new Vue() is only necessary for the root component instance.

Hide vue router from a page

Is it possible to hide the vue-router from my login page? If so, how would I do that? On every page I have I see the menu, but on the Login page I don't want to see it.
Here is my code:
Login
<template>
<div>
<h1>Login</h1>
<form action="">
<label>naam</label>
<input type="text">
</form>
</div>
</template>
<script>
</script>
<style scoped>
h1 {
background-color: chartreuse;
}
</style>
App.vue
<template>
<div id="app">
<div class="routing">
</div>
<router-link to="/">Login</router-link>
<router-link to="/home">Home</router-link>
<router-view v-if="$route = 'login'"></router-view>
</div>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>
Main.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import Login from './Login.vue'
import Home from './Home.vue'
Vue.use(VueRouter);
const routes = [
{ path: '/', component: Login},
{ path: '/home', component: Home},
];
const router = new VueRouter({
routes,
mode: 'history'
});
new Vue({
el: '#app',
router,
render: h => h(App)
});
Home.vue
<template>
<div>
<h1>Home</h1>
<hr>
<router-view></router-view>
</div>
</template>
<script>
</script>
<style scoped>
h1 {
background-color: aquamarine;
}
</style>
I just had the same problem and found 2 approaches:
1. Using nested routes - http://router.vuejs.org/en/essentials/nested-routes.html
Basically you have to use your App.vue as kind of a placeholder, with all the elements that are shared between all the pages (in your case I believe that is none), and place <router-view></router-view> inside it. For you I believe that will be as simples as:
//App.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
And you also will have to have another template that will hold your menu:
//Restricted.vue
<template>
<div id="restricted">
<div class="routing">
</div>
<router-link to="/">Login</router-link>
<router-link to="/home">Home</router-link>
<router-view></router-view>
</div>
</template>
And in your router should have something like:
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import Login from './Login.vue'
import Home from './Home.vue'
import Restricted from '/.Restricted.vue';
Vue.use(VueRouter);
const routes = [
{ path: '/', component: Login},
{
path: '/restricted',
component: Restricted,
children: [
{ path: 'home', component: Home},
],
},
];
const router = new VueRouter({
routes,
mode: 'history'
});
new Vue({
el: '#app',
router,
render: h => h(App)
});
This way your Login page will be rendered at / and other pages (with menu) at /restricted/{other_page}. Using this approach the menu will not be displayed nor rendered.
2. Using v-if on the components that you do not want to render.
In you App.vue use v-if="this.$route.path !== '/'" on the elements that you do not want to be rendered, in your case, the router-link's. You could encapsulate them and apply v-if="this.$route.path !== '/'" to the encapsulation element (div?)
//App.vue
<template>
<div id="app">
<div class="routing" v-if="this.$route.path !== '/'">
<router-link to="/">Login</router-link>
<router-link to="/home">Home</router-link>
</div>
<router-view></router-view>
</div>
</template>
Regards.
You can use v-if for this:
<router-link v-if="!isOnLoginPage()" to="/">Login</router-link>
where isOnLoginPage can be a simple method, which returns true or false depending on current route.
isOnLoginPage: function() {
return this.$route.path === '/'
}
if your login path is '/login'
in your App.vue
<template>
<div id="app">
<div class="routing">
</div>
<router-link to="/" v-if="$route.fullPath !== '/login'">Login</router-link>
<router-link to="/home" v-if="$route.fullPath !== '/login'">Home</router-link>
<router-view v-if="$route.fullPath === '/login'"></router-view>
</div>
</template>
<script>
export default {
data () {
return {
}
}
}
</script>

Categories

Resources