How to make this Vue.js component to work? - vue.js

I have this component with default data that I want to reuse on other pages with other data:
CustomCard.vue
<template>
<div>
<v-layout >
<v-flex md4 class="white">
<div>
<slot class="top-img">
<img src="../assets/default.jpg" alt="">
</slot>
<slot class="description">
<p>default description</p>
</slot>
</div>
</v-flex>
</v-layout>
</div>
</template>
<script>
export default {
}
</script>
Page1.vue
<template>
<div>
<custom-card>
</custom-card>
</div>
</template>
<script>
export default {
}
</script>
Question:
What should I do in order to use CustomCard.vue component on Page1.vue page with another data:
src="../assets/image1.jpg"
"changed description"

You should import the component CustomCard in the component where you want to use it, and then add it in components option from your vue object.
After this you are ready to use it in your template.
<template>
<div id="app">
<custom-card/>
</div>
</template>
<script>
import CustomCard from './components/CustomCard' . // <-- This
export default {
components: {
CustomCard // <--This
}
}
If you want to use different data... you can pass them by props like this:
<custom-card :data="newData"/>

Related

Vue.js child component to populate the slots of a dynamic component inside parent component

How can I render the header slot to the table component from the child component? This code is not working:
Table component
<template>
<div>
<slot name="header"></slot>
</div>
</template>
Parent component
<template>
<div>
<component :is="currentComponent" > </component>
</div>
</template>
<script>
export default {
data() {
return {
currentComponent: 'Table'
};
},
};
</script>
Child component
<template>
<div>
<parent-component>
<template slot="header">
<h1>test</h1>
</template>
</parent-component>
</div>
</template>
Tried the code above but it dosent work
Expecting to render title from child component
Solution:
Table component
<template>
<div>
<slot name="header"></slot>
</div>
</template>
Parent component
**<template>
<div>
<component :is="currentComponent" >
<template v-for="(_, name) in $slots" #[name]="slotData">
<slot :name="name" v-bind="slotData || {}" />
</template>
</component>
</div>
</template>**
<script>
export default {
data() {
return {
currentComponent: 'Table'
};
},
};
</script>
Child component
<template>
<div>
<parent-component>
<template slot="header">
<h1>test</h1>
</template>
</parent-component>
</div>
</template>

Include Modal.vue in page1.vue and page2.vue

I started using Laravel with vue.js, i have created some pages using vue.js
so i have modal that i would like to use in both of pages ( page1.vue and page2.vue ) without re write the modal html code again:
Page1.vue
<template>
<div>Page 1 </div>
</template>
Page2.vue
<template>
<div>Page 2 </div>
</template>
How can i share a modal.vue with this two pages
Just import the modal component into both pages. Here ive done it with a bool modalBool that will toggle weather the modal is displayed or not.
<template>
<div>
Page 1
<modal v-if="modalBool"> </modal>
</div>
</template>
<script>
import Modal from "./Modal.vue";
export default {
components: {
Modal,
},
data() {
return {
modalBool: false,
};
},
};
</script>
<style lang="scss" scoped></style>
You can add things like on close to reset the bool in the parent
<template>
<div>
Page 1
<modal v-if="modalBool" v-on:close="showInvitationModal = false"> </modal>
</div>
</template>
Here is an example of my modal that will emit close when closed. The parent is listening for this close and will reset the modalBool. This will be emitted if the user clicks outside of the modal or on the X
<template>
<transition name="component-fade" mode="out-in">
<div class="modal-background" #click.self="$emit('close')">
<div class="modal-body shadow">
<h2 class="modal-title">
<div>{{ title }}</div>
<div>
<button class="btn-clear" #click="$emit('close');">
<font-awesome-icon :icon="timesIcon" class="pointer" />
</button>
</div>
</h2>
<div>
<slot></slot>
</div>
</div>
</div>
</transition>
</template>

How to pass data to the $slots in child component?

I have two components
Navigation
Alert
Alert is Navigation's child
Navigation code
<template>
<div class="col-lg-5">
<base-alert :icon="`fa fa-facebook`"></base-alert>
</div>
</template>
<script>
export default {
data() {
return {
error: 'This is error'
}
}
}
</script>
Base alert code
<slot>
<span v-if="icon" class="alert-inner--icon">
<i :class="icon"></i>
</span>
<span v-if="$slots.text" class="alert-inner--text">
<slot name="text"></slot>
</span>
</slot>
Currently this is what I got
My problem right now how do i pass the error data to the base-alert $slots.text?
Regards
You need to add <template slot="text">{{ error }}</template> as below. Where text is the name of slot you have mentioned in Base Alert
Navigation Code
<template>
<div class="col-lg-5">
<base-alert :icon="`fa fa-facebook`">
<template slot="text">{{ error }}</template>
</base-alert>
</div>
</template>
<script>
import baseAlert from "./base-alert";
export default {
components: { baseAlert },
data() {
return {
error: "This is error"
}
}
}
</script>
Base Alert
<template>
<div>
<slot>
<span v-if="icon" class="alert-inner--icon">
<i :class="icon"></i>
</span>
<span v-if="$slots.text" class="alert-inner--text">
<slot name="text"></slot>
</span>
</slot>
</div>
</template>
<script>
export default {
name: "base-alert",
props: ["icon"]
};
</script>
<style scoped></style>
Pass your error message down as a prop to the child.
Navigation code
<template>
<div class="col-lg-5">
<base-alert :error="error" :icon="`fa fa-facebook`"></base-alert>
</div>
</template>
<script>
export default {
data() {
return {
error: 'This is error'
}
}
}
</script>
Base alert code
<slot>
<span v-if="icon" class="alert-inner--icon">
<i :class="icon"></i>
</span>
<span v-if="error" class="alert-inner--text">
<div>{{ error }}</div>
</span>
</slot>

Why always include "v-else" template block?

I have two templates on components and one flag.
<template v-if="mainPage">
<div class="col-md-12">
<h1>1 page</h1>
</div>
</template>
<template v-else>
<div class="col-md-12">
<h1>2 page</h1>
</div>
</template>
export default {
data () {
return {
text : '',
mainPage: true,
}
},
but default include second template. why?
First of all, when creating a vuejs you are only allowed one root element per component, so without the v-else part your component wouldnt work, unless you change template to div, and create one parent template:
If you don't want to use v-if you can just use v-show as:
<template v-show="mainPage">
<div class="col-md-12">
<h1>1 page</h1>
</div>
</template>
<template>
<div class="col-md-12">
<h1>2 page</h1>
</div>
</template>
This will not work for templates though. Because you can not have two templates in vuejs components

vue-multiselect does not load CSS

I am using vue-multiselect component (b15) with vue-cli (webpack template) but the component's CSS is not loaded and the component renders wrong. Any idea?
My code:
<template>
<div>
<div class="select2-container select2-container-multi full-width">
<multiselect
class="form-control form-control-select textarea"
:class="{ 'has-error': showError }"
:options="localOptions"
:label="labelKey"
track-by="id"
:multiple="multiple"
:selected="value"
:searchable="true"
:placeholder="placeholder"
:loading="loading"
:custom-label="formatLabel"
:disabled="disabled"
:readonly="readonly"
#input="updateSelected"
#close="blur">
</multiselect>
</div>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
export default {
mixins: [inputMixin],
components: {
Multiselect
}
}
</script>
Multiselect is rendered and everything just no style is applied.
You need to add css seperately at the end, so you file looks like that:
<template>
<div>
<div class="select2-container select2-container-multi full-width">
<multiselect
class="form-control form-control-select textarea"
:class="{ 'has-error': showError }"
#input="updateSelected"
#close="blur">
</multiselect>
</div>
</div>
</template>
<script>
import Multiselect from 'vue-multiselect'
export default {
mixins: [inputMixin],
components: {
Multiselect
}
}
</script>
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>