How to obtain data in child component in Vue.js 3? - data-binding

I have a Date component that contains a calendar and time. I can select a date and time from this. I have another component called DatePopup that shows a calendar and time as a popup. This component contains OK and Cancel buttons. If a user selects OK, I want to get the date reactive variable in child component, i.e., Date.
How can I achieve this structure so that I can obtain the data from parent component?
Note that I use Quasar.
Date.vue
<template>
<div class="q-pa-md q-gutter-sm">
<q-badge color="yellow-illerarasi-film-teskilati" text-color="black">
Deadline: {{ date.full }}
</q-badge>
</div>
<div class="q-gutter-md row items-start">
<q-date v-model="date.full" mask="YYYY-MM-DD HH:mm" color="yellow-illerarasi-film-teskilati" text-color="black"/>
<q-time v-model="date.full" mask="YYYY-MM-DD HH:mm" color="yellow-illerarasi-film-teskilati" text-color="black"/>
</div>
<p> {{ date }}</p>
</template>
<script>
import {reactive} from "vue";
export default {
name: "Date",
setup() {
let date = reactive({
full: "2022-01-01 00:00",
})
return {
date,
}
}
}
</script>
<style scoped>
</style>
DatePopup.vue
<template>
<div class="q-pa-md q-gutter-sm">
<q-dialog v-model="show">
<q-card style="width: 700px; max-width: 80vw;">
<q-card-section>
<div class="text-h6">Choose a Deadline</div>
</q-card-section>
<q-card-section class="q-pt-none">
<Date/>
</q-card-section>
<q-card-actions align="right">
<q-btn flat label="Cancel" color="primary" text-color="black" v-close-popup/>
<q-btn label="OK" color="yellow-illerarasi-film-teskilati" text-color="black" v-close-popup/>
</q-card-actions>
</q-card>
</q-dialog>
</div>
</template>
<script>
import Date from "./Date.vue";
import {reactive} from "vue";
export default {
name: "DatePopup",
components: {Date},
props: {
showPopup: {
type: Boolean,
default: true
}
},
setup(props) {
return reactive({
show: true
})
}
}
</script>
<style scoped>
</style>

Related

vuejs3: how to init a ref using a prop?

I have this codes
<script setup>
defineProps({
position: { type: String, required: false, default: "center middle" },
});
</scritp>
I am trying adding this after defineProps
const myPosition = ref(position);
But I got
Uncaught (in promise) ReferenceError: position is not defined
What am I doing wrong, and, important, why?
To initialize a prop using the "Component" API along with <script setup>, you will want to assign the object returned by the defineProps(...) macro a name, say props and use that variable name when referring to the props in your script. So if you have a prop declared like so:
const props = defineProps({
position: { type: String, required: false, default: "center middle" },
});
You can use it in the same script like so:
const myLocation = ref(props.position);
So, a complete example could look like so:
ParentComponent.vue
<template>
<div class="main-body">
<h1>Parent Component</h1>
<div class="grid-container">
<div>
Position (in Parent):
</div>
<div>
<input v-model="msg">
</div>
</div>
<hr>
<div>
<Child :position="msg" title="Child Component 1"/>
</div>
<div>
<Child title="Child Component 2 (default position property)"/>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import Child from './Child.vue'
const msg = ref('North West')
</script>
<style>
.main-body {
margin: 10px 20px;
}
.grid-container {
display: grid;
grid-template-columns: 1fr 2fr;
}
</style>
and then
Child.vue
<template>
<h2>
{{ title }}
</h2>
<div class="grid-container">
<div>
Position (from parent):
</div>
<div>
{{ position }}
</div>
<div>
My Position:
</div>
<div>
<input type="text" v-model="myLocation">
</div>
<div>
My Position:
</div>
<div>
{{ myLocation }}
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
const props = defineProps({
position: { type: String, required: false, default: "center middle" },
title: { type: String, required: false, default: "ChildComponent"}
});
const myLocation = ref(props.position);
</script>
<style scoped>
.grid-container {
display: grid;
grid-template-columns: 1fr 2fr;
}
</style>
Also, please check out this code in the Vue Playground
In this example, the myPosition field is initialized with the prop, but then once the application has been launched, this field is no longer dependent on the prop.
At first, you code is not fully enough. Where do you try to const myPosition = ref(position);?
If you define your props right, then there is no need to apply ref or reactive to them. They are reactive already.
Simply use now you position in the component.
Here is the sample from the Vue Tutorial Step 12 Props
<!-- ChildComp.vue -->
<script setup>
const props = defineProps({
msg: String
})
</script>
and
<ChildComp :msg="greeting" />

Children Component HTML not visible in VueJS

I have create Home Component which is imported into App.vue
App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png" />
<home></home>
</template>
<script>
import home from "./components/home.vue";
export default {
name: "App",
components: {
home
},
};
</script>
And header component is imported into Home.vue
Home.vue
<template>
<header></header>
</template>
<script>
import header from "./header.vue";
export default {
name: "home",
components: {
header: header,
},
};
</script>
Header.vue
<template>
<div class="new-component">
<h1>A New Component</h1>
<p>This is a text inside the NewComponent.</p>
</div>
</template>
<script>
export default {
name: 'header',
}
</script>
When I check in browser I don't see HTML of header.vue
Use multi word names. Your component is conflicting with HTML's default header tag.
VueHeader.vue
<template>
<div class="new-component">
<h1>A New Component</h1>
<p>This is a text inside the NewComponent.</p>
</div>
</template>
<script>
export default {
name: "vue-header",
};
</script>
Home.vue
<template>
<vue-header></vue-header>
</template>
<script>
import VueHeader from "./VueHeader.vue";
export default {
name: "home",
components: {
VueHeader,
},
};
</script>
You can find more information about this and other minor issues in here Vue style guide

How to change component css with props with Nuxt Js Vue js

I'm new to Nuxt and Vue, thanks for being indulgent ;).
I have a "Subtitle" component that I use in another "Main" component (names are for the example).
How can I change the css of the "subtitle" component from the "Main" component ?
Here "Subtitle" component :
<template>
<div>
<h1 :class="data">{{ title }}</h1>
</div>
</template>
<script>
export default {
name: 'subtitle',
props: {
title: String,
}
}
</script>
And here my "Main" component :
<template>
<div class="container">
<Subtitle :title="title""></Subtitle>
</div>
</template>
I searched with the props etc.... But now I've been on it for a while and I'm blocking.
Thanks for your help!
You can do it using the combination of props and computed
Subtitle Component
<template>
<div>
<h1 :style="getStyle">{{ title }}</h1>
</div>
</template>
<script>
export default {
name: 'subtitle',
props: {
stylings: Object,
},
computed: {
getStyle() {
return this.stylings;
}
}
}
</script>
Main Component
<template>
<div class="container">
<Subtitle :stylings="customStyle"></Subtitle>
</div>
</template>
export default {
name: 'subtitle',
data() {
return {
customStyle: {
'font-weight': 'Bold',
}
}
}

How to arrange elements in Vuejs component

I have a component in Vue like this:
Tags.vue
<template>
<div>
<v-chip
v-for="tag in tags"
:key="tag"
class="ma-2"
label
x-small
color="blue"
text-color="white"
>
{{ tag }}
</v-chip>
</div>
</template>
<script>
export default {
name: 'Tags',
props: {
tags: {
type: Array,
default: () => ['Empty'],
},
},
}
</script>
This is the result
How can I make them appear one below the other instead of side by side?
This should be a css questions. Add a class "container" for the wrapper div and put some css into it. You can use flex-box
<div class="container">
<v-chip
v-for="tag in tags"
:key="tag"
class="ma-2"
label
x-small
color="blue"
text-color="white"
>
{{ tag }}
</v-chip>
</div>
<style lang="scss" scoped>
.container{
display: flex,
flex-direction: 'column'
}
</style>
This is another solution without css:
I use tag https://vuetifyjs.com/en/components/chip-groups/
<template>
<div class="container">
<v-chip-group column active-class="primary--text">
<v-chip
v-for="tag in tags"
:key="tag"
class="ma-2"
outlined
x-small
color="blue"
text-color="blue"
>
{{ tag }}
</v-chip>
</v-chip-group>
</div>
</template>
<script>
export default {
name: 'Tags',
props: {
tags: {
type: Array,
default: () => ['Empty'],
},
},
}
</script>

same component with different background-color

I've created a component and use it multiple times on one of my vue pages.
Now I wanna change the background-color for each use of this component.
This is my component:
<template>
<div class="project-card" :style="{backgroundColor: color}">
<h2>{{ title }}</h2>
<p>{{ description }}</p>
</div>
</template>
<script>
export default {
name: 'ProjectCard',
props: {
title: String,
description: String
},
data: function() {
return {
color: "#000"
}
}
}
</script>
and this is my vue page, where I use the component:
<template>
<div class="projects">
<ProjectCard
title="Projekt 01"
description="Lorem Ipsum"
/>
<ProjectCard
title="Projekt 02"
description="Lorem Ipsum"
/>
</template>
<script>
import ProjectCard from '#/components/ProjectCard.vue'
export default {
name: 'projects',
components: {
ProjectCard
}
}
</script>
Is it now possible to change the color data of the project-card component on my projects page, like I changed the text props?
Thanks for your help!
Pass color also as a prop:
<ProjectCard
title="Projekt 02"
description="Lorem Ipsum"
color= "#000F"
/>
<ProjectCard
title="Projekt 02"
description="Lorem Ipsum"
color= "#00FF00"
/>
and in script:
<script>
export default {
name: 'ProjectCard',
props: {
title: String,
description: String,
color:String
},
data: function() {
return {
color: "#000"
}
}
}
</script>

Resources