I have a very basic basic component
testcomponent
<template>
<div class="test">
<h1>testing</h1>
</div>
</template>
Then i have a main component, where i have a button that, when pressed, should open a sweet alert and the content of the alert should be testcomponent.
I tried this:
<template>
<v-btn #click="showAlert"
outlined
small
tile
style="color: white"
>Open</v-btn>
</template>
<script>
export default {
props:{
},
data() {
},
mounted() {
},
methods: {
showAlert() {
// Use sweetalert2
this.$swal.fire({html: '<testcomponent></testcomponent>'});
},
}
}
</script>
The problem with this code is that the component is not loaded, i see a blank space. Is there any way to do this? Thanks in advance!
Related
I'm implementing an application with Vue Js and I've the following code:
<template>
<simple-page title="list-patient" folder="Patient" page="List Patient" :loading="loading">
<list-patients #patientsLoaded="onPatientsLoaded"/>
</simple-page>
</template>
Both simple-page and list-patients are custom components created by me. Inside ListPatients I've an HTTP request on Create callback, as follows:
created() {
axios.get("...").then(response => {
...
this.$emit('patientsLoaded');
})
},
Then, my objective is to handle the patientsLoaded event and uptade the loading prop on the top parent component, as follows:
data() {
return {
loading: true
}
},
methods: {
onPatientsLoaded(params) {
this.loading = false;
}
}
However, the created method is not being triggered inside the list-patients component. The only way I can make this work is by removing :loading.
Any one can help?
Edit 1
Code of simple page:
<template>
<section :id="id">
<!-- Breadcrumb-->
<breadcumb :page="page" :folder="folder"/>
<!-- Breadcrumb-->
<!-- Simple Card-->
<simple-card :title="page" :icon="icon" :loading="loading" v-slot:body>
<slot>
</slot>
</simple-card>
<!-- Simple Card-->
</section>
</template>
Code of simple card:
<b-card>
<!-- Page body-->
<slot name="body" v-if="!loading">
</slot>
<!--Is loading-->
<div class="loading-container text-center d-block">
<div v-if="loading" class="spinner sm spinner-primary"></div>
</div>
</b-card>
Your list-patients component goes in the slot with name "body". That slot has a v-if directive so basically it is not rendered and hooks are not reachable as well. Maybe changing v-if to v-show will somehow help you in that situation. Anyway, you have deeply nested slots and it is making things messy. I usually declare loading variable inside of the component, where fetching data will be rendered.
For example:
data () {
return {
loading: true;
};
},
mounted() {
axios.get('url')
.then(res => {
this.loading = false;
})
}
and in your template:
<div v-if="!loading">
<p>{{fetchedData}}</p>
</div>
<loading-spinner v-else></loading-spinner>
idk maybe that's not best practise solution
v-slot for named slots can be indicated in template tag only
I suppose you wished to place passed default slot as body slot to simple-card component? If so you should indicate v-slot not in simple-card itself but in a content you passed it it.
<simple-card :title="page" :icon="icon" :loading="loading">
<template v-slot:body>
<slot>
</slot>
</template>
</simple-card>
I'm attempting to use Vue Material on a Vue Router Dashboard page, but I'm trying to store the panel in a separate file. I'm absolutely clueless as to why this is not working, I've spent the last 2 hours googling this issue and I don't have anything. Even using the Vue chrome extension doesn't show it, which rules out styling. Putting a red background color on the component does work, yet it still does not work. And also, please forgive my bad code-- I'm about 3 days into Vue.
<template>
<div class="page-container md-layout-row">
<md-app>
<md-app-toolbar class="md-primary">
<span class="md-title">{{ usernameTitleCase }}</span>
</md-app-toolbar>
<PagePanel></PagePanel>
<md-app-content>
<div class="user">
<h1>{{ user.username }}</h1>
<h2>{{ user.customThing }}</h2>
<h3>{{ user.id }}</h3>
</div>
</md-app-content>
</md-app>
</div>
</template>
<script>
import PagePanel from '#/components/panel.vue';
export default {
name: 'Dashboard',
components: {
PagePanel
},
data() {
return {}
},
computed: {
usernameTitleCase() {
const letters = this.user.username.split('');
letters[0] = letters[0].toUpperCase();
return letters.join('')
}
},
created() {
this.user = JSON.parse(localStorage.getItem('user'));
}
}
</script>
<style>
.md-app {
min-height: 350px;
}
.md-drawer {
width: 230px;
max-width: calc(100vw - 125px);
}
</style>
Component File Here:
<template>
<md-app-drawer md-permanent="full">
<md-toolbar class="md-transparent" md-elevation="0">
Navigation
</md-toolbar>
<md-list>
<md-list-item>
<md-icon>move_to_inbox</md-icon>
<span class="md-list-item-text">Inbox</span>
</md-list-item>
<md-list-item>
<md-icon>send</md-icon>
<span class="md-list-item-text">Sent Mail</span>
</md-list-item>
<md-list-item>
<md-icon>delete</md-icon>
<span class="md-list-item-text">Trash</span>
</md-list-item>
<md-list-item>
<md-icon>error</md-icon>
<span class="md-list-item-text">Spam</span>
</md-list-item>
</md-list>
</md-app-drawer>
</template>
<script>
export default {
name: 'PagePanel'
}
</script>
I'm also NOT in production mode and am not getting any errors in console.
It's not easy to spot, but towards the end of this page of the VueMaterial docs, it says:
In these examples we have 3 distinct areas: Toolbar, Drawer and Content. You should create them using the following tags:
md-app-toolbar: ...
md-app-drawer: ...
md-app-content: ...
Any other tag passed as a direct child of the md-app tag will be ignored. The component will only look for these three tags and choose the right placement for them.
Fortunately, they added the ability to use slots (but didn't document them, you have to look at merge requests to see it). You can use them like so:
<template>
<div class="page-container md-layout-row">
<md-app>
<md-app-toolbar> ... </md-app-toolbar>
<page-panel slot="md-app-drawer"></page-panel>
<md-app-content> ... </md-app-content>
</md-app>
</div>
</template>
However, note that the slot value can only be one of the 3 values defined above.
I have two components and one of them doesnt want to render. It even appears in DOM. I would think I messed up some paths and so on, but if it shows in DOM then evrything is alright. I dont event know what part of code to attach over here for you to view.. so will attach
picture of a DOM
the beggining of my App.vue
<template>
<div>
<field-modal></field-modal>
<form> // All below just renders fine
<div class="progress">
<div class="progress-bar" :style="progressBar"></div>
</div>
<fileds-registration v-for="(field, i) in info">
</fileds-registration>
<button class="btn btn-primary" :disabled="!isButton">
Send Data
</button>
</form>
</div>
</template>
<script>
import FiledsRegistration from './components/Action.vue';
import FieldModal from './components/Modal.vue';
export default {
components: {
FiledsRegistration,
FieldModal
},
data(){ .......
And my whole component Modal.vue file which doesnt want to render
<template>
<div class="modal">
<p>Here we go</p>
</div>
</template>
<script>
export default
{
components: {
},
data(){
return {
}
}
}
</script>
<style scoped>
.modal
{
width: 500px;
height: 500px;
background: blue;
}
<style>
I'm trying to use slots to inject content from a parent component to its child, but Vue keeps rendering the default content, not parsing the content sent from its parent.
This is the code of the parent component, which in turn is a child of a global component:
let parentComponent = {
template: `
<div>
<child-component>
<template v-slot:action>Close</template>
<template v-slot:element>Modal</template>
</child-component>
</div>
`,
components: {
'child-component': childComponent
}
};
And here is its child component, where I want to pass content:
let childComponent = {
template: `
<button>
<slot name="action">Open</slot>
<slot name="element">Window</slot>
</button>
`,
};
The button is still displaying the default content: "Open Window"
What am I doing wrong?
EDIT:
This is the rest of the content, just in case it helps:
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>VueJS</title>
</head>
<body>
<div id="app">
<vue-directives></vue-directives>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.16/dist/vue.js"></script>
<script src="components/slotDirective/slotDirectiveSubcomponent.js"></script>
<script src="components/slotDirective/slotDirective.js"></script>
<script src="components/VueDirectives.js"></script>
<script>
let vue = new Vue({
el: '#app'
});
</script>
</body>
</html>
And VueDirectives.js:
Vue.component('vue-directives', {
template: `
<div>
<h3>{{ title }}</h3>
<parentComponent/>
</div>
`,
data() {
return {
title: "VueJS directives",
}
},
components: {
parentComponent
}
});
I fixed the error. I don't know the reason, but it wasn't working either if I loaded Vue.js from a CDN, or if I manually downloaded it locally, as a single file.
Then I finally tried installing it from npm, and loading Vue.js in node_modules/vue/dist/vue.js, and this way it works. I assume otherwise Vue.js does not comply with all its functionality.
I'm not sure that slots are designed for this. If you are just changing the text of a button passing props into the parentComponent is how i would go about it. E.g.
<parentComponent buttonText="some text or bind with a data value or computed prop"/>
see: https://v2.vuejs.org/v2/guide/components-props.html
Using slots... If you are experimenting try this, a reusable dialog box that you can pop in anywhere and control the content. E.g.
// myDialog
<v-dialog>
<slot>Here you can put what you want</slot>
</v-dialog>
And to use:
<myDialog>
<template>
<myContent /> Or just put content here without another component
</template>
</myDialog>
I am currently writing a Vue component for a project.
I encountered a Problem where a Bootstrap-Vue modal will re open again instead of closing.
I am using Vue.js in Version 2.6.10 and Bootstrap 4.
<template>
<div>
<b-button v-b-modal.rating-modal #click="showModal()">
Click me
<b-modal ref="rating-modal" no-close-on-backdrop centered title="Rate" class="rating-modal" #ok="hideModal" #cancel="hideModal" #close="hideModal">
<div>
Content of the modal...
</div>
</b-modal>
</b-button>
</div>
</template>
<script>
export default {
name: "Rating",
components: {
,
},
methods: {
showModal() {
this.$refs['rating-modal'].show();
},
hideModal() {
this.$refs['rating-modal'].hide();
},
}
}
;
</script>
I expect it to close when I hit either cancel, ok or the cross in the header.
Ok, I resolved the Issue by myself. All I had to do is to move the b-modal tag out of the b-button tag like this:
<template>
<div>
<b-button v-b-modal.rating-modal #click="showModal()">
Click me
</b-button>
<b-modal ref="rating-modal" no-close-on-backdrop centered title="Rate" class="rating-modal" #ok="hideModal" #cancel="hideModal" #close="hideModal">
<div>
Content of the modal...
</div>
</b-modal>
</div>
</template>