Initializing a variable of a child from a parent - vue.js

I have a variable in my parent component and would like it to be sent to the child component.
I tried several ways but nothing works on my side, here is my code:
Parent :
<template>
<Widget/>
</template>
<script>
import Widget from './Widget'
export default {
data () {
return {
model: {
data: 'data send !'
}
}
},
components: {
Widget
},
methods: {
}
}
</script>
Child :
<template>
<div class="row">
<div class="box">
<p> {{data}} </p>
</div>
</div>
</template>
<script>
export default {
data () {
return {
data: '111'
}
}
}
</script>
<style scoped>
.box {
box-shadow: 10px 10px 5px grey;
}
</style>
thank you in advance for your help!

To bind data to a child component you can use props.
Parent :
<template>
<Widget :data="model.data"/>
</template>
<script>
import Widget from "./Widget";
export default {
data() {
return {
model: {
data: "data send !"
}
};
},
components: {
Widget
},
methods: {}
};
</script>
Child:
<template>
<div class="row">
<div class="box">
<p>{{data}}</p>
</div>
</div>
</template>
<script>
export default {
props: ["data"]
};
</script>
<style scoped>
.box {
box-shadow: 10px 10px 5px grey;
}
</style>

Related

Vuejs2.6 - Images not loading

I know there are several other questions about it, but none of them seems to help me.
I'm trying to create a simple Image component, but I images are not loading since I tried to use them in a component.
<template>
<!-- <img :click="go()" :src="require(`../assets/img/${filename}`)"> -->
<img :click="go()" :src="`../assets/img/'${filename}`">
</template>
<script>
export default {
name: 'Imagem',
data() {
return {
filename: ''
}
},
methods: {
go() {
console.log('image click')
}
}
}
</script>
<style scoped>
img{
min-width: 20%;
}
</style>
The first line throws error:
The second line, without require, gives no error but don't load the image (i restarted the project and cleaned cache)
This is the view where Imagem component is imported:
<template>
<div class="login-images">
<!-- <img #click="novoProfessor" src="../assets/professor.png" alt="" srcset="">
<img #click="novoAluno" src="../assets/aluno.png" alt="" srcset=""> -->
<Imagem :filename="'professor.png'" />
<Imagem :filename="'aluno.png'" />
</div>
</template>
<script>
import Imagem from '../components/Imagem';
export default {
name: 'Login',
components: {
Imagem
},
props: {
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.login-images {
min-width: 100%;
min-height: 50%;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
.login-images > * {
margin: 10%;
}
</style>
Change your Imagem component like this:
<template>
<img :src="imageURL" #click="go">
</template>
<script>
export default
{
name: 'Imagem',
props:
{
filename:
{
type: 'String',
required: true
}
},
computed:
{
imageURL()
{
return `../assets/img/${this.filename}`;
}
},
methods:
{
go(event)
{
console.log('You clicked on the "' + event.target.src + '"');
}
}
}
</script>

Nuxt - Using router.push inside a component not changing pages correctly

index.vue -
<template>
<div>
<Header />
<div class="container">
<SearchForm />
</div>
</div>
</template>
<script>
const Cookie = process.client ? require('js-cookie') : undefined
export default {
data() {
return {
form: {
email: '',
password: ''
},
show: true
}
},
methods: {
logout() {
// Code will also be required to invalidate the JWT Cookie on external API
Cookie.remove('auth')
this.$store.commit('setAuth', {
auth: null,
user_type: null
})
}
}
}
</script>
<style>
.container {
/* margin: 0 auto; */
/* min-height: 100vh; */
display: flex;
justify-content: center;
align-items: center;
text-align: center;
}
</style>
jobs.vue -
<template>
<div>
<Header />
<SearchForm />
<b-container class="main_container">
<b-row>
<h1> Results for "{{q}}"</h1>
</b-row>
<b-row>
<ul id="array-rendering">
<li v-for="item in results" :key="item.job_id">
{{ item.job_title }}
{{ item.job_city }}
{{ item.job_state }}
{{ item.job_work_remote }}
</li>
</ul>
</b-row>
</b-container>
</div>
</template>
<script>
const Cookie = process.client ? require('js-cookie') : undefined
export default {
// middleware: 'notAuthenticated',
watchQuery: ['q'],
data() {
return {
q: null,
results: []
}
},
async fetch() {
this.q = this.$route.query.q
this.results = await this.$axios.$get('/api/job/search', {
params: {
keyword: this.q,
}
})
},
methods: {
}
}
</script>
<style>
.container {
align-items: center;
text-align: center;
}
</style>
SearchForm.vue component -
<template>
<div id='searchFormDiv'>
<b-form inline #submit.prevent="onSubmit">
<label class="sr-only" for="inline-form-input-name"> keyword</label>
<b-form-input v-model="form.keyword" id="inline-form-input-name" class="mb-2 mr-sm-2 mb-sm-0" placeholder="Job title or keyword" size="lg"></b-form-input>
<label class="sr-only" for="inline-form-input-username">location</label>
<b-input-group class="mb-2 mr-sm-2 mb-sm-0">
<b-form-input v-model="form.location" id="inline-form-input-username" size="lg" placeholder="City, state or zip"></b-form-input>
</b-input-group>
<b-button type="submit" variant="primary">Find Jobs</b-button>
</b-form>
</div>
</template>
<script>
import {
BIconSearch,
BIconGeoAlt
} from 'bootstrap-vue'
export default {
data() {
return {
form: {
keyword: '',
location: ''
}
}
},
created () {
this.form.keyword = this.$route.query.q
},
methods: {
onSubmit() {
this.$router.push({
path: 'jobs',
query: {
q: this.form.keyword
}
});
}
},
components: {
BIconSearch,
BIconGeoAlt
},
}
</script>
<style>
#searchFormDiv {
margin-top: 50px
}
</style>
The route for "http://localhost:3000/" returns the index.vue page.
In this vue page, I have a component with a search form. Once you complete these form and hit the seach button, it will re-direct to a results page
if this.form.keyword = "Data", the next URL will be "http://localhost:3000/jobs?q=Data" and it will be using the jobs.vue page.
The issue I'm running into is the CSS is not being loaded from the jobs.vue page. It's still coming from the index.vue page for some reason. If I refresh the page, then the CSS from jobs.vue is loading. I need the CSS to load from jobs.vue on the initial redirect. All of the query data is working as expected so thats a plus.
However, the following CSS is being applied from index.vue for some reason instead of the CSS from the jobs.vue page -
display: flex;
justify-content: center;
Does anyone know whats going on here? This app is SSR and not SPA.
You have to scope your css from the index.vue page to the other pages with the scoped directive (see docs https://vue-loader.vuejs.org/guide/scoped-css.html)
<style scoped>
/* local styles */
</style>
<style>
/* global styles */
</style>
You can add your global CSS in your layouts/default.vue file.
This solved the issue -
methods: {
onSubmit() {
window.location = 'http://localhost:3000/jobs?q=' + this.form.keyword;
}
},

Delivery data from parent to child

After googling for hours and trying all king examples I still can't figure out how to call to a function that located in a child or pass any data to a child from the parent. I tried so many examples without success and i got really confused with the Vue, is it so complicated to pass a data to a child? Here is what I came up with from one of the examples but it does not work with me, maybe I do something wrong here? Thanks :(
parent.vue
<template>
export default {
name:'parent'
data:{
retrun:{
dataTochild:''
}
},
methods:{
callToChild:function(){
this.dataTochild = 'Hello Child'
}
}
}
</template>
<child :myprop="dataTochild" />
<input #click="this.callToChild" />
child.vue
<template>
export default {
name:'child',
props:['myprop'],
watch:{
myprop:function(){
alert('Hello Parent')
}
}
}
<template>
By the way, I am using Vue 2 version!
you have a spelling error on return (retrun), and there could be other errors on code you have omitted.
Working live demo
Here it is working on a live demo
Code
Parent
<template>
<div class="parent">
<child :myprop="dataTochild" />
<button #click="callToChild">Press me!</button>
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
name: "Parent",
data() {
return {
dataTochild: "",
counter: 0
};
},
methods: {
callToChild: function() {
this.counter = this.counter + 1;
this.dataTochild = "Hello Child " + this.counter;
}
},
components: {
Child
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
button {
width: 200px;
height: 60px;
}
</style>
Child
<template>
<div class="child">
<p>{{ myprop }}</p>
</div>
</template>
<script>
export default {
name: "Child",
props: ["myprop"],
watch: {
myprop: function() {
console.log("Hello Parent");
alert("Hello Parent");
}
}
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
div.child {
width: 400px;
height: 100px;
margin: auto;
}
</style>

HeaderComponent with custom functionality

I would like to know how can I implement a CustomHeader with a custom functionality (other than sort, for example).
Basically what I want to know is how to communicate my HeaderComponent with my component that holds the grid. E.g.:
<template>
<div style="height: 100%" class="table-chart" ref="root">
<div class="title" ref="title">{{ objectData.title }}</div>
<div class="ag-dashboard" style="height: 100%; width: 90%; margin: 0 auto">
<ag-grid-vue
:style="{ height: tableHeight }"
:gridOptions="gridOptions"
:columnDefs="columnDefs"
:rowData="rowData"
/>
</div>
</div>
</template>
<script>
export default {
components: {
'HeaderComponent': {
template: '<span>{{this.params.displayName}} <span #click="custom">CLICK</span></span>',
methods: {
custom() {
// emmit an event here or find a way to comunnicate with the function "customEvent" below
}
}
}
},
methods: {
customEvent() {
console.log('Event from header');
}
},
beforeMount() {
// ... setup Ag-Grid and the HeaderComponent in the columns' headerComponentFramework
}
}
</script>
Apreciate any help,
The cleaner way I found of doing this was through an EventBus:
import Vue from 'vue';
const EventBus = new Vue();
export default {
//...
'HeaderComponent': {
// ...
methods: {
custom() {
EventBus.$emit('customEvent');
}
}
// ...
mounted() {
EventBus.$on('customEvent', () => {
// Do whatever...
});
}
}

Use method in template, out of instance vue

This is warning when i click on go to contact in tab about: "Property or method "switchTo" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option.
(found in component )."
How do I fix this?
new Vue({
el: '#app',
data: {
currentPage: 'home',
},
methods: {
switchTo: function(page) {
this.currentPage = page;
}
},
components: {
home: {
template: `#home`,
},
about: {
template: `#about`,
},
contact: {
template: '#contact'
}
}
})
.navigation {
margin: 10px 0;
}
.navigation ul {
margin: 0;
padding: 0;
}
.navigation ul li {
display: inline-block;
margin-right: 20px;
}
input, label, button {
display: block
}
input, textarea {
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<div id="app">
<div class="navigation">
<ul>
<li>Home</li>
<li>About</li>
</ul>
</div>
<div class="pages">
<keep-alive>
<component v-bind:is="currentPage">
</component>
</keep-alive>
</div>
</div>
<template id="home">
<p>home</p>
</template>
<template id="about">
<p>about go to contact</p>
</template>
<template id="contact">
<p>contact</p>
</template>
Just change your about template to this
<template id="about">
<p>about go to contact</p>
</template>
new Vue({
el: '#app',
data: {
currentPage: 'home',
},
methods: {
switchTo: function(page) {
this.currentPage = page;
}
},
components: {
home: {
template: `#home`,
},
about: {
template: `#about`,
},
contact: {
template: '#contact'
}
}
})
.navigation {
margin: 10px 0;
}
.navigation ul {
margin: 0;
padding: 0;
}
.navigation ul li {
display: inline-block;
margin-right: 20px;
}
input, label, button {
display: block
}
input, textarea {
margin-bottom: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.js"></script>
<div id="app">
<div class="navigation">
<ul>
<li>Home</li>
<li>About</li>
</ul>
</div>
<div class="pages">
<keep-alive>
<component v-bind:is="currentPage">
</component>
</keep-alive>
</div>
</div>
<template id="home">
<p>home</p>
</template>
<template id="about">
<p>about go to contact</p>
</template>
<template id="contact">
<p>contact</p>
</template>
I already solved a problem like this in this question: Calling methods in Vue build
It's not the same problem so it's not a repeated question, but the answer is the same:
In the created hook, add the component to window.componentInstance like this:
methods: {
foo () {
console.log('bar')
}
},
created () {
window.componentInstance = this
}
Then you can call the method anywhere like this:
window.componentInstance.foo()