Vue: remove a component when other is completely loaded - vue.js

<template>
<div id="app">
<Loading></Loading>
<Content></Content>
</div>
</template>
<script>
import Loading from './Loading.vue'
import Content from './Content.vue'
export default {
name: 'App',
components: {
Loading,
Content
}
}
</script>
What is the best and elegant way to handle a loading component and remove it (or vue component or change styles) when all page is loaded?
I tried with v-cloack, but I think its not working beyond data stuff.
I tried with mounted, but doesn't seems to work.

v-cloak is to hide un-compiled mustache bindings until the Vue instance is ready. So you can use v-if to show/hide loading component.
var child1 = Vue.extend({
template: "<div>Loading...</div>"
});
var child2 = Vue.extend({
template: "<div>After Component loaded</div>",
});
var app = new Vue({
el: "#vue-instance",
data: {
loading: true
},
mounted() {
var vm = this;
setTimeout(function() {
vm.loading = false;
}, 1000);
},
components: {
child1,
child2
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.1/vue.js"></script>
<div id="vue-instance">
<child1 :name="name" v-if="loading"></child1>
<child2 :name="name" v-if="!loading"></child2>
</div>

Related

set default map centering with props in vue

I'm using vue to make an arc gis driven application, because the map's center can changed based on user location, I am setting the default location to some props then passing them into my map component to be called in the map components mounted() hook for rendering.
I think i'm pretty close to doing this correctly but when I log my props in my map component in the console it says they're undefined.
I'm not sure if my app code is at fault or my child component code?
as you can see in my app.vue I am even trying to pass in plain integers to test the values and they are still undefined.
app.vue
<template>
<div id="app">
<web-map v-bind:centerX="-118" v-bind:centerY="34" />
<div class="center">
<b-button class="btn-block" #click="getLocation" variant="primary">My Location</b-button>
</div>
</div>
</template>
<script>
import WebMap from './components/webmap.vue';
export default {
name: 'App',
components: { WebMap },
data(){
return{
lat: -118,
long: 34
}
},
};
</script>
webmap.vue
<template>
<div></div>
</template>
<script>
import { loadModules } from 'esri-loader';
export default {
name: 'web-map',
props:['centerX, centerY'],
data: function(){
return{
X: this.centerX,
Y: this.centerY
}
},
mounted() {
console.log(this.X,this.Y)
// lazy load the required ArcGIS API for JavaScript modules and CSS
loadModules(['esri/Map', 'esri/views/MapView'], { css: true })
.then(([ArcGISMap, MapView]) => {
const map = new ArcGISMap({
basemap: 'topo-vector'
});
this.view = new MapView({
container: this.$el,
map: map,
center: [this.X,this.Y], ///USE PROPS HERE FOR NEW CENTER
zoom: 8
});
});
},
beforeDestroy() {
if (this.view) {
// destroy the map view
this.view.container = null;
}
}
};
</script>
There is a typo. Change:
props:['centerX, centerY'],
to:
props:['centerX', 'centerY'],

Vue Component mounted before mounting the dependencies when using http-vue-loader

I have a parent component (CyaCandidateItem) that has a slot to render a child component (CyaCandidateItemActions). A wrapper component (CyaInformativeCandidateItem) injects the child component into the parent's slot.
new Vue({
el: '#main',
components: {
'CyaInformativeCandidateItem': Vue.component('CyaInformativeCandidateItem', {
name: 'CyaInformativeCandidateItem',
template: `
<cya-candidate-item ref="self">
<cya-candidate-item-actions slot="action-buttons" ref="actions"></cya-candidate-item-actions>
</cya-candidate-item>`,
components: {
'CyaCandidateItem': Vue.component('CyaCandidateItem',{ // EMBEDDED component
name: 'CyaCandidateItem',
template: `
<div>
<slot name="action-buttons"></slot>
</div>
`
}),
'CyaCandidateItemActions': Vue.component('CyaCandidateItemActions',{
name: 'CyaCandidateItemActions',
template : `
<div class="actions">
<button>Hallo</button>
</div>`,
data: function(){
return {};
}
})
},
mounted: function(){
console.log('mounted', this.$refs.actions, this.$refs.self, this.$refs);
}
})
},
mounted: function(){}
});
Till thins everything works fine. $refs.actions and $refs.self points to the valid element. But when I render CyaCandidateItem through http-vue-loader both $refs.actions and $refs.self is undefined.
'CyaCandidateItem': httpVueLoader('/assets/CyaCandidateItem.vue')
Seems like the dependent component is being mounted before mounting the dependencies.
I this the expected behavour when using http-vue-loader ?

How to transfer data between components in Vue.js?

I'm trying to transfer data form my main vue js to a vue component. My project is built with laravel. I've app.js that mainly work for vue. And also have other components. I would like to transfer data between them.
Please check my code.
This is my app.js
require('./bootstrap');
import Vue from "vue";
import VueResource from 'vue-resource'
Vue.use(VueResource);
Vue.http.headers.common['X-CSRF-TOKEN'] = $('input[name="csrf-token"]').attr('value');
Vue.component('google-map', require('./components/GoogleMap.vue'));
const app = new Vue({
el: '#app',
data: {
lat: 0,
lng: 0,
center: { lat: 45.508, lng: -73.587 },
},
created(){
this.lat = 34.20;
this.lng = 100.36;
this.setCenter();
},
methods: {
setCenter(){
this.center.lat = parseFloat(this.lat);
this.center.lng = parseFloat(this.lng);
}
}
});
This is my GoogleMap.vue
<template>
<div>
</div>
</template>
<script>
export default {
name: "GoogleMap",
data() {
return {
center: { lat: 45.508, lng: -73.587 },
};
},
mounted() {
this.centerFun();
},
methods: {
centerFun(){
console.log(this.center);
}
}
};
</script>
This is my map.php
<html>
<head>
<title>Map</title>
</head>
<body>
<div id="app">
<label>Lat</label><input type="text" name="" v-model="lat" #keyup="testFun">
<label>Lng</label><input type="text" name="" v-model="lng" #keyup="testFun">
<google-map></google-map>
</div>
<script type="text/javascript" src="js/app.js"></script>
</body>
</html>
You can see there are two "center" var.
Can I bind those to a single one? Or what can I do?
If I've multiple components, how can I transfer data form app.js to those components or those components to app.js?
Update GoogleMap.vue to this:
<template>
<div>
</div>
</template>
<script>
export default {
name: "GoogleMap",
props: ['center'],
data() {
return {
// center: { lat: 45.508, lng: -73.587 },
};
},
mounted() {
// this.centerFun();
},
methods: {
//centerFun(){
// console.log(this.center);
//}
}
};
</script>
...so that it can accept the center prop from the parent component. And then send center from your parent component to googlemap component like this:
<google-map :center="center"></google-map>
As #AlxTheRed mentioned, more info about how props work can be found at:
https://v2.vuejs.org/v2/guide/components-props.html
You can pass values from parent component to child component via props.
Declare the variables you want from the parent component as props in child component.
In parent component, where you are including your child component:
<child-comp var1="abc" :var2="xyz"></child-comp>
In child component's instance, declare these as props:
props: ['var1','var2'],
Now, in child component, you can directly access them as:
this.var1
Read more here:
https://v2.vuejs.org/v2/guide/components.html
If your structure contains many dependencies, I suggest you to use vuex.

Vuejs props use in the client component

Hi I'm trying to pass a value to a child component as props and trying to use this value in child's created hook but it's not getting set. See example below,
<!-- Parent component -->
<template>
<div>
<details
:customer_id = this.customer_id
:foo = "bar" />
</div>
</template>
<script>
import CustomerDetail from './CustomerDetails';
export default {
name: 'Customer',
data: function() {
return {
customer_id: '',
}
components: {
'detail': CustomerDetail
},
created: function() {
var id = this.$route.params.id;
this.customer_id = id;
} // created
}
</script>
<!-- Details component -->
<template>
<div>
<h1>{{foo}}</h1>
</div>
</template>
<script>
export default {
name: 'CustomerDetail',
props: ['customer_id', 'foo']
created: function() {
console.log(this.customer_id); <!-- -->
} // created
}
</script>
As shown in above code, when child component is rendered, may times the customer_id in created() hook of child component is undefined. It shows up occasionally if hotloading happens on the same view. How do I make sure that this value always available. In this case I want to do server call to get customer details. At the same time {{foo}} correctly show value 'bar'. What am I missing? Any help is appreciated.
Registered child components actually have direct access to the route params, since you are using Dynamic Route Matching, you can simply get the dynamic params via $routes.params.* from the child components themselves.
const Customer = {
template: `
<div>
<h3>Customer ID: {{$route.params.id}}</h3>
</div>
`
}
const routes = [
{ path: '/customers/:id', component: Customer }
];
new Vue({
el: '#app',
router: new VueRouter({
routes
}),
data() {
return {
bar: 'Doh!',
//customer_id: '',
}
},
components: {
CustomerDetails: {
template: `
<div>
<h1>Value from parent: <em>{{foo}}</em></h1>
</div>
`,
props: ['foo']
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.2/vue-router.min.js"></script>
<div id="app">
<div>
<label>View profile:</label>
<router-link to="/customers/john">John</router-link>
<router-link to="/customers/doe">Doe</router-link>
<router-view></router-view>
<div>
<customer-details :foo="bar"></customer-details>
</div>

Component does not show in vue

I do not get vue components really .... I have a vue component in my html and want to show it, but it does not show anything, what do I do wrong?
What is the proper way to register and show a component in vue? Can someone give me a simple example for a beginner? :)
This is my code:
HTML
<div id="na-vue-app">
<activity-filter>
<template>
'Some Text'
</template>
</activity-filter>
</div>
Vue
new Vue({
el: '#na-vue-app'
});
const filterActivity = Vue.extend({
data: function () {
return {
distance:100,
}
},
mounted() {
},
methods: {
}
});
Vue.component('activity-filter', filterActivity);
Look at this pen: https://codepen.io/Nartub600/pen/oopBYJ
HTML
<div id="app">
<my-component msg="Hi!">
</my-component>
</div>
JS
Vue.component('my-component', {
props: ['msg'],
template: '<p>{{ msg }}</p>'
})
var app = new Vue({
el: '#app'
})
It's the easiest form to try components I think