How to pull different components into divs with v-for? - javascript

I'm trying to get different components into tabs content here https://codepen.io/iTaurus85/pen/KbrBEa
When switching tabs I need to get the content from those components. BUt I just get a text.
How can I solve this problem? Or maybe I have chosen the wrong way to show different pages via tabs?
<div id="app">
<v-content>
<v-layout row wrap class="tab-layout">
<v-toolbar color="cyan" dark tabs>
<v-toolbar-side-icon></v-toolbar-side-icon>
<v-toolbar-title>Page title</v-toolbar-title>
<v-spacer></v-spacer>
<v-btn icon>
<v-icon>search</v-icon>
</v-btn>
<v-btn icon>
<v-icon>more_vert</v-icon>
</v-btn>
<v-tabs
slot="extension"
v-model="tab"
color="cyan"
align-with-title
>
<v-tabs-slider color="yellow"></v-tabs-slider>
<v-tab v-for="item in levels" :key="item">
{{ item.name }}
</v-tab>
</v-tabs>
</v-toolbar>
<v-tabs-items v-model="tab">
<v-tab-item v-for="item in levels" :key="item">
<v-card flat>
{{ item.content }}
</v-card>
</v-tab-item>
</v-tabs-items>
</v-layout>
</v-content>
</div>
new Vue({
el: '#app',
// components:{
// intro,
// Elementary,
// },
data () {
return {
tab: null,
levels: [
{name:'Beginner', content: '<intro></intro>'},
{name:'Elementary', content: '<elementary></elementary>'},
{name:'Pre-Intermediate', content: 'Pre-Intermediate'},
{name:'Intermediate', content: 'Intermediate'},
{name:'Upper-Intermediate', content: 'Upper-Intermediate'}
]
}
}
})

The answer is here https://v2.vuejs.org/v2/guide/components.html#Dynamic-Components.
This example https://jsfiddle.net/chrisvfritz/o3nycadu/ showed exactly what I wanted.
<script src="https://unpkg.com/vue"></script>
<div id="dynamic-component-demo" class="demo">
<button
v-for="tab in tabs"
v-bind:key="tab"
v-bind:class="['tab-button', { active: currentTab === tab }]"
v-on:click="currentTab = tab"
>{{ tab }}</button>
<component
v-bind:is="currentTabComponent"
class="tab"
></component>
</div>
Vue.component('tab-home', {
template: '<div>Home component</div>'
})
Vue.component('tab-posts', {
template: '<div>Posts component</div>'
})
Vue.component('tab-archive', {
template: '<div>Archive component</div>'
})
new Vue({
el: '#dynamic-component-demo',
data: {
currentTab: 'Home',
tabs: ['Home', 'Posts', 'Archive']
},
computed: {
currentTabComponent: function () {
return 'tab-' + this.currentTab.toLowerCase()
}
}
})
.tab-button {
padding: 6px 10px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
border: 1px solid #ccc;
cursor: pointer;
background: #f0f0f0;
margin-bottom: -1px;
margin-right: -1px;
}
.tab-button:hover {
background: #e0e0e0;
}
.tab-button.active {
background: #e0e0e0;
}
.tab {
border: 1px solid #ccc;
padding: 10px;
}

You can use v-html directive: https://v2.vuejs.org/v2/guide/syntax.html#Raw-HTML - codepen: https://codepen.io/anon/pen/EGOOym.
But a better approach would be create separate components for each tab.

You can use is (Vue :is) for your v-for + components for each tab:
<div v-for="item in items"><component :is="item.componentName"></component></div>
Your item can be something like:
{componentName: 'Intermidiate', tasks: 100}
And in a Vue instance you should also add component like:
new Vuew({
components: {
Inetrmidiate,
}
})
And the last point - just create new Vue-component named Intermidiate.

Related

How to customize vuetify carousel arrows?

Hello i have the following template in my application:
<v-carousel cycle height="300" class="carousel" hide-delimiters>
<template v-slot:prev="{ on, attrs }">
<v-btn fab :color="theme.highlightColor" v-bind="attrs" v-on="on"
><v-icon>mdi-arrow-left</v-icon></v-btn
>
</template>
<template v-slot:next="{ on, attrs }">
<v-btn fab :color="theme.highlightColor" v-bind="attrs" v-on="on"
><v-icon>mdi-arrow-right</v-icon></v-btn
>
</template>
<v-carousel-item
v-for="i in 4"
:key="i"
:src="photo"
></v-carousel-item>
</v-carousel>
I wanted to customize arrows responsible for changing the slide. For this purpose, according to vuetify documentation i've used prev, and next slot. The problem is my code has no influence on the look of mentioned arrows. Also no errors are logged to the console. What am i doing wrong? How to customize carousel arrows?
This is working exemple. Something more is needed ???
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
colors: [
'indigo',
'warning',
'pink darken-2',
'red lighten-1',
'deep-purple accent-4',
],
slides: [
'First',
'Second',
'Third',
'Fourth',
'Fifth',
],
}
},
})
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.x/dist/vuetify.js"></script>
<div id="app">
<v-app id="inspire">
<v-carousel
cycle
height="400"
hide-delimiter-background
show-arrows-on-hover
>
<template v-slot:prev="{ on, attrs }">
<v-btn
color="success"
v-bind="attrs"
v-on="on"
>PREV #Bulchsu</v-btn>
</template>
<template v-slot:next="{ on, attrs }">
<v-btn
color="info"
v-bind="attrs"
v-on="on"
>NEXT #Bulchsu</v-btn>
</template>
<v-carousel-item
v-for="(slide, i) in slides"
:key="i"
>
<v-sheet
:color="colors[i]"
height="100%"
>
<v-row
class="fill-height"
align="center"
justify="center"
>
<div class="display-3">
{{ slide }} Slide
</div>
</v-row>
</v-sheet>
</v-carousel-item>
</v-carousel>
</v-app>
</div>
As I imagine that the solutions proposed at the beginning in the doc are not worth it delimiter-icon="mdi-icon".
Because this only allows you to change the background icon image and has an extra difficulty to change it in the moments that are active.
I can suggest something simple and very efficient for this case
clean the limiter icon on the carrousel delimiter-icon=""
assign your carousel a css class <v-carousel class="cssClass".....
include in the corresponding class the css classes to change
.cssClass { .v-btn {
color: transparent !important;
border: 1px solid red !important;
background-color: transparent !important;
}
.v-btn--active {
color: red !important;
border: 1px solid red !important;
background-color: red !important;
}
}
it would look something like this
<v-carousel class="cssClass"
v-model="model"
cycle
delimiter-icon="">
....
</v-carousel>
Once this is done, the result of the carrousel will now be the following
I hope I have helped, regards.

For loop in both parent and child component vuejs

I want to display items of each category.
For this I have a parent component that passes the category to the child component and it filters out the items based on that category and shows it for each of the categories. The child component loops through the items in that category.
The item array contains items of all category. I cant quite get the idea on how to do this and which lifecycle hooks I should use.
If anyone would take a look that would be appreciated.
The Parent Component:
<template>
<div>
<home-categories v-for="category in storeCategories" :key="category.name" :category="category.name"></home-categories>
</div>
</template>
<script>
import HomeCategories from "#/components/home/HomeCategories";
export default {
name: "HomeCategoryParent",
components: {
HomeCategories
},
created() {
this.$store.dispatch("bindStoreCategories")
},
computed: {
storeCategories() {
return this.$store.getters.storeCategories;
}
}
}
</script>
<style scoped>
</style>
The Child Component:
<template>
<v-container fluid style="margin-top: -20px;" class="google-font">
<p
class="google-font mt-0 mb-0"
style="font-weight: 200; font-size: 120%; padding: 0px;"
>
<b>{{ category }}</b>
</p>
<v-card
class="d-flex flex-row disableScroll"
flat
tile
style="margin-top: 16px; padding: 2px; overflow-x: auto;"
>
<v-card max-width="250" v-for="item in items" :key="item.name">
<v-img
class="white--text align-end"
height="200px"
src="../../assets/img/category_blank.jpg"
>
<v-card-title>{{ item.ITEM_NAME }}</v-card-title>
</v-img>
<v-card-subtitle class="pb-0">{{item.price}}</v-card-subtitle>
<v-card-text class="text--primary">
<div>{{item.desc}}</div>
<div>{{item.unit}}</div>
</v-card-text>
<v-card-actions>
<v-btn color="orange" text>
Add
</v-btn>
</v-card-actions>
</v-card>
</v-card>
</v-container>
</template>
<script>
export default {
data() {
return {
items: []
}
},
name: "HomeCategories",
props: ["category"],
created() {
this.$store.dispatch("bindStoreItems");
let all_items = this.$store.getters.storeItems;
this.items = this.$store.getters.storeItems;
all_items.forEach(item => {
let itemObj = {
category: null,
name: null,
desc: null,
price: null,
unit: null,
isAvail: null,
}
if(item.CATEGORY === this.category){
itemObj.category = item.CATEGORY;
itemObj.name = item.ITEM_NAME;
itemObj.desc = item.ITEM_DESC;
itemObj.price = item.ITEM_PRICE;
itemObj.unit =item.ITEM_UNIT;
itemObj.isAvail =item.ITEM_AVAIL;
this.items.push(itemObj);
}
})
},
};
</script>
<style scoped></style>

How to making <v-list-item> menus responsive when scrolling down in vue-fullpage.js

I am creating a homepage using vuetify and vue-fullpage.js
picture
When you click on the menu, go to the page and active pink color.
But... How to making menus responsive when scrolling down..
Main.vue
<template>
<div>
<v-navigation-drawer nav app floating>
<menu-bar />
</v-navigation-drawer>
<v-container fluid>
<full-page :options="options" id="fullpage" fluid>
<div class="section" v-bind="user">
<intro-page :userInfo="user[0].name" />
</div>
<div class="section" v-bind="user">
<about-page :userInfo="user" />
</div>
<div class="section" v-bind="skill">
<skill-page :skillInfo="skill" />
</div>
<div class="section" v-for="(project, index) in projects" :key="index">
<project-page :projectInfo="project" />
</div>
</full-page>
</v-container>
</div>
</template>
<script>
import MenuBar from "#/components/MenuBar.vue";
import IntroPage from "#/components/IntroPage.vue";
import AboutPage from "#/components/AboutPage.vue";
import SkillPage from "#/components/SkillPage.vue";
import ProjectPage from "#/components/ProjectPage.vue";
export default {
name: "Main",
components: {
MenuBar,
IntroPage,
AboutPage,
SkillPage,
ProjectPage
},
data() {
return {
options: {
anchors: ["About", "Contact", "Skill", "Project"],
}
};
}
};
</script>
../src/views/Main.page menu-bar Component
MenuBar.vue
<template>
<v-card flat id="menu">
<v-list>
<v-list-item-group color="pink">
<v-list-item
v-for="(item, index) in items"
:key="item.title"
:href="link[index]"
activator
class="overflow-y-auto"
>
<v-list-item-content>
<v-list-item-title v-text="item.title"
><a v-bind:href="link[index]"></a
></v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-item-group>
</v-list>
</v-card>
</template>
<script>
export default {
data() {
return {
drawer: true,
items: [
{ title: "About", icon: "mdi-help-box" },
{ title: "Contact", icon: "mdi-phone" },
{ title: "Skill", icon: "mdi-gavel" },
{ title: "Project", icon: "mdi-folder-pound" }
],
link: ["#About", "#Contact", "#Skill", "#Project"],
right: false,
permanent: true,
background: false
};
},
};
</script>
<style scoped>
a {
text-decoration: none;
}
#menu {
position: fixed;
z-index: 99;
top: 30%;
left: 20%;
}
</style>
How to making menus responsive when scrolling down?

Why is this.$refs undefined in Vue child component?

I'm working on a drag and drop component in Vue but when I try to access the form using this.$refs, it is returning undefined. I'm using the dialog UI component from Vuetify to place my upload form into a dialog/modal.
CodePen
The dialog is a child component to another component, and the form isn't visible until after the "Add Attachments" button is clicked. I suspect the later is the issue, but I'm unsure how to solve it. I figured placing the code under the mounted life-cycle hook would do the trick but I understand that runs immediately when it renders the button into the parent component.
<template>
<v-dialog v-model="dialog" persistent max-width="600px" style="z-index:999;">
<template v-slot:activator="{ on }">
<v-btn small outlined color="#102a43" v-on="on">Add Attachments</v-btn>
</template>
<v-card>
<v-card-text class="pt-4">
<v-container class="my-4">
<form ref="fileform" class="file-upload-form">
<div v-if="dragAndDropCapable" class="dropzone">
<p>
Drop your file here, or
<span>browse</span>
</p>
<p>Supported File Types: pdf, jpg, png</p>
</div>
<div v-else>
<v-file-input label="Select File" outlined dense></v-file-input>
</div>
</form>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="#b2b2b2" text #click="cancel">Cancel</v-btn>
<v-btn color="#102a43" outlined>Upload</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
data: function() {
return {
files: [],
dialog: false,
dragAndDropCapable: false
};
},
methods: {
isDragAndDropCapable() {
const div = document.createElement("div");
return (
("draggable" in div || ("ondragstart" in div && "ondrop" in div)) &&
"FormData" in window &&
"FileReader" in window
);
},
cancel() {
this.dialog = false;
}
},
mounted() {
//Verify Drag and Drop Capability
this.dragAndDropCapable = this.isDragAndDropCapable();
//Code below return undefined - Expected behavior is to return form element
console.log(this.$refs.fileform);
}
};
</script>
<style lang="scss" scoped>
.dropzone {
border: 2px dashed #90a4ae;
border-radius: 8px;
min-height: 5rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
&:hover {
cursor: pointer;
}
p {
margin-bottom: 0;
&:first-of-type {
font-weight: 500;
font-size: 1rem;
color: #263238;
span {
color: #62b0e8;
}
}
&:last-of-type {
font-size: 0.8rem;
}
}
}
</style>
By default content within v-dialog components isn't rendered until it is activated.
Add the eager attribute to change this <v-dialog eager>
https://vuetifyjs.com/en/components/dialogs/
On mounted, the v-dialog isnt actually mounted or lets say its not initialized.
I have modified your CodePen.
Try this eager prop of the v-dialog like this below :
<v-app id="app">
<v-app id="inspire">
<v-dialog v-model="dialog" persistent max-width="600px" eager>
<template v-slot:activator="{ on }">
<v-btn color="red lighten-2"
dark
v-on="on">Add Attachments</v-btn>
</template>
<v-card>
<v-card-text class="pt-4">
<v-container class="my-4">
<form ref="fileform" class="file-upload-form">
<div v-if="dragAndDropCapable" class="dropzone">
<p>
Drop your file here, or
<span>browse</span>
</p>
<p>Supported File Types: pdf, jpg, png</p>
</div>
<div v-else>
<v-file-input label="Select File" outlined dense></v-file-input>
</div>
</form>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="#b2b2b2" text #click="cancel">Cancel</v-btn>
<v-btn color="#102a43" outlined>Upload</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-app>
</div>

How to list the items correctly with v-for?

Can anyone help me with this? https://codepen.io/iTaurus85/pen/aRNWdy
I can't make PriceItems.text.content appear in v-list-tile-title using v-for. I want to have something like: Testing plan: Full access, -, -, -. Basic plan: Full access, Support, Chat, -. etc. according to PriceItems.text
<div id="app">
<v-app id="inspire">
<v-flex xs4 v-for="item in PriceItems" :key="item.title" :class="item.class" >
<h3 class="price__block-title">{{item.title}}</h3>
<h5 class="price__block-subtitle">{{item.subTitle}}</h5>
<v-list dense class="price__block-list">
<v-list-tile class="price__block-item">
<v-list-tile-content>
<v-list-tile-title class="text-xs-center" >
{{item.text.content}}
</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-divider></v-divider>
</v-list>
</v-flex>
</v-app>
</div>
.price__block{
display: flex;
align-items: center;
flex-direction: column;
background-color: #00a1c7;
margin: 5px;
}
.v-list.price__block-list {
background: transparent;
}
new Vue({
el: '#app',
data: function() {
return {
PriceItems: [
{class:'price__block price__block-testing',title:'Testing',subTitle:'1 day',
text:[
{content:'Full access'},
{content:' - '},
{content:' - '},
{content:' - '}
]},
{class:'price__block price__block-testing',title:'Basic',subTitle:'7 days',
text:[
{content:'Full access'},
{content:'Support'},
{content:'Chat'},
{content:'-'}
]},
{class:'price__block price__block-testing',title:'Standart',subTitle:'30 days',
text:[
{content:'Full access'},
{content:'Support'},
{content:'Chat'},
{content:'Call'}
]},
{class:'price__block price__block-testing',title:'Premium',subTitle:'120 days',
text:[
{content:'Full access'},
{content:'Support'},
{content:'Call'},
{content:'Chat'}
]},
]
}
}
})
Your child content is an array, so you need iterator for that too, just like you did for priceitems v-for="item in PriceItems"
<v-list-tile-title class="text-xs-center" v-for="itemContent in item.text">
{{itemContent.content}}
</v-list-tile-title>
Demo

Categories

Resources