string which is sent to other compononent with router.push is undefined - vue.js

Well, I have two components. From one component I would like to send a string to another component where the string should be displayed on the console. This is the component where the data is pushed to the other component:
this.$router.push({path: "/editService", params:{data: 'test'}})
This is the second component. In here the string should be displayed:
export default {
data(){
return{
ServiceData: []
}
},
created() {
this.ServiceData=this.$route.params.data
console.log(this.ServiceData)
}
}

If you are using Vue Router, then you should have a route defined similar to
{
path: '/editService/:routeData',
component: User,
props: true
}
then add a prop to your user component:
export default {
data(){
return{
ServiceData: this.routeData
}
},
props: {
routeData: {
type: String, // at least for test
required: true
}
},
created() {
console.log(this.ServiceData)
}
}

Related

Vue: Not rendering the component for the second time on routing

I am facing behavior of Vue which I don't understand. I am using routing between components.
methods: {
redirectToLogin() {
this.$router.push("/login");
},
redirectToRegister() {
this.$router.push("/register");
}
}
So when load the app, route Login component, login successfully and then log out to component with methods above. After this when I am trying to route to login again the Login component is not rendered, but the route is shown in the address line
Below you can see my routes
routes: [
{path: '/', name: 'Hello', component: Hello},
{path: "/login",name:'Login', component: Login},
{path: "/register",name:'Register', component: Register},
{path: "/user/:id",name:'User', component: User},
{path: "/reset",name:'PasswordReset', component: PasswordReset},
]
I am also using Vuex can it somehow affect such behaviour?
UPD:
When I log out I see the following error in my console
TypeError: "t._data is undefined"
VueJS 14
$destroy
destroy
_
T
x
$
ji
_update
r
get
run
Yn
he
ue
vue.runtime.esm.js:1888:12
UPD 2 : Components
This is first component loaded to the app. After logging out route leads here and none of the router links work
export default {
name: 'Hello',
data() {
return {
msg: 'Work With your projects in agile manner'
}
}
}
Login component
export default {
name: "Login",
data() {
return {
errorOccurred: false,
errorMessage: '',
credentials: {
login: '',
password: ''
},
remember: false
}
},
methods: {
submit() {
this.$store.dispatch('loginUser', this.credentials).then(() => {
this.errorMessage = this.getError;
if (this.errorMessage.length) {
this.errorOccurred = true;
} else {
this.$router.push({path: '/user/' + this.getId});
}
});
this.errorOccurred = false;
},
resetPassword() {
this.$router.push("/reset");
},
},
computed: {
loginValidation() {
return this.credentials.login.length > 0
},
passwordValidation() {
return this.credentials.password.length > 0
},
getError() {
return this.$store.getters.getErrorMsg;
},
getId() {
return this.$store.getters.getUserId;
}
},
}
User component routed from login.
import NavbarCommon from "./NavbarCommon";
export default {
name: "User",
components: {NavbarCommon},
data(){
},
methods: {
loadAvatar(){
let image = '../../assets/emptyAvatar.png';
if ('avatar' in this.getUser){
image = this.getUser.avatar;
}
return image;
}
},
computed:{
getUser() {
return this.$store.getters.getUser;
}
}
}
And two two more components.
NavbarComponent - common navbar for several components
import NavbarRight from "./NavbarRight";
export default {
name: "NavbarCommon",
components: {NavbarRight},
methods:{
routeToUser(){
this.$router.push({path: '/user/' + this.getUser});
},
routeToProject(){
this.$router.push({path: '/project/' + this.getProject});
}
},
computed:{
getUser() {
return this.$store.getters.getUserId;
},
getProject(){
//TODO:
return 'get project id'
}
}
}
And right part of Navbar with logout button
export default {
name: "NavbarRight",
methods:{
logOut(){
this.$store.dispatch('logOutUser').then(()=>{
this.$router.push('/');
});
},
}
}
So the problem is really stupid.
In User component data missed return.
After adding
data(){
return {}
},
Everything started working

Is it possible to dynamically add chart type in the extends: property, based on props from parent component?

I have a vue chartjs component which imports the whole vue-chartjs library. My idea is, is it possible to somehow pass the type of the chart which I want and add it to the 'extends: VueCharts.charttype?.' In the example I provide it extends the VueCharts.Line, I need this property to be dynamically interpolated, passed from props. Is it possible this charttype to come from a parent props dynamically and how?
<script>
import { VueCharts } from "vue-chartjs";
export default {
extends: VueCharts.Line,
props: ["chartdata", "options"],
mounted() {
this.renderChart(this.chartdata, this.options);
}
}
</script>
<style scoped>
</style>
since extends the same as mixins, you need to pass a dynamic mixin, in order to do that you need two components, imagine we have component ChartWrapper :
<template>
<div>
<div>{{ chartType }}</div>
<chart :chart-data="datacollection"/>
</div>
</template>
<script>
import Chart from "./Chart";
import { VueCharts, mixins } from "vue-chartjs";
const { reactiveProp } = mixins;
export default {
name: "ChartWrapper",
components: {
Chart
},
props: {
chartType: {
type: String,
required: true
}
},
data() {
return {
datacollection: {
labels: [this.getRandomInt(), this.getRandomInt()],
datasets: [
{
label: "Data One",
backgroundColor: "#f87979",
data: [this.getRandomInt(), this.getRandomInt()]
},
{
label: "Data One",
backgroundColor: "#f87979",
data: [this.getRandomInt(), this.getRandomInt()]
}
]
}
};
},
methods: {
getRandomInt() {
return Math.floor(Math.random() * (50 - 5 + 1)) + 5;
}
},
created() {
if (this.chartType) {
Chart.mixins = [reactiveProp,VueCharts[this.chartType]];
}
}
};
</script>
this component takes chartType as a prop, and I import all charts as VueCharts in top of the script ==> 1
second component:
<script>
export default {
props: ["options"],
mounted() {
// this.chartData is created in the mixin.
// If you want to pass options please create a local options object
this.renderChart(this.chartData, this.options);
}
};
</script>
the second component just has options props, and renderChart function invoked.
==> 2
What is happening?
the ChartWrapper component receives the chart type by chartType prop, in the created hook, if chartType exist, assign the chart(resolved by VueCharts[this.chartType]) to Chart component as a mixin in addition to reactiveProp,
I also pass the chart data to Chart component.
in the end, call the ChartWrapper component:
<ChartWrapper chartType="Bar"/>
Live example on code sandbox: https://codesandbox.io/s/vue-template-w9r8k
You can also choose for the option to just extend the Line chart and update the config of the chart with the chart type you want and give it an update so it changes type.
<script>
import { Line, mixins } from 'vue-chartjs';
const { reactiveProp } = mixins;
export default {
extends: Line,
name: "LineChart",
mixins: [reactiveProp],
props: {
options: { type: Object },
chartType: { type: String }
},
mounted () {
this.renderChart(this.chartData, this.options);
},
watch: {
options: {
deep: true,
handler () {
this.$data._chart.options = this.options;
this.updateChart();
}
},
chartType (newVal) {
this.$data._chart.config.type = newVal;
this.updateChart()
}
},
methods: {
updateChart () {
this.$data._chart.update();
},
}
}
</script>

How to track changes to the injected root instance property

I have a property injected like so:
Vue.prototype.$authentication = {
authenticated: false,
user: ""
};
and its working fine.
then in another component I want to track/watch the property changes. How do I do it ?
EDIT
I want to be able to do it like this:
<script>
export default {
name: "Login",
data: function(){
return {
isLoggedIn: this.$authentication.authenticated
}
},
watch: {
isLoggedIn(){
console.log('its working');
}
},
}
</script>
but the thing is, the code wouldn't work.
Have it solved by looking at the api doc. So in my component file, I simply do it like so:
<script>
export default {
name: "Login",
data: function(){
return {
isLoggedIn: this.$authentication // remove the attribute
}
},
watch: {
'isLoggedIn.authenticated': function (){ // now access the attribute
console.log('its working');
}
},
}
</script>
now it is all good.

Props not passed to the dynamic component

I'm rendering a dynamic component:
<component :is="element.name == 'text' ? element.component : false" v-bind="elementProps"></component>
with:
computed: {
element() {
return {
name: this.elementObject.type,
component: {
components: { TextInput },
template: `<text-input :form-id="formId"
:section-id="sectionId"
:element-id="elementId"
id="test2"
></text-input>`
},
}
},
elementProps() {
const props = {
formId: this.formId,
sectionId: this.sectionId,
elementId: this.elementId,
id: this.generateId()
};
return props;
},
}
.. but I get an error Property or method "formId" is not defined on the instance but referenced during render. although I am passing in the props. What am I doing wrong?
You forgot to define the props when you create the component in the element function, try:
component: {
components: { TextInput },
template: `<text-input :form-id="formId"
:section-id="sectionId"
:element-id="elementId"
id="test2"></text-input>`,
props: ['formId', 'sectionId', 'elementId', 'id']
},
formId, sectionId and elementId in the template have to be defined somewhere in the component either as props, data or computed property.

Invalid prop type from router params, expected Number got String

I am trying to collect id value from URL.
Previously I take help in this post.
In my index.js of router file I have below code:
{ path: '/word/:id',
name: 'word',
component: Word,
props: true,
},
In my component I have below code:
<script>
export default {
props: {
id: Number,
},
created() {
this.routeChanged();
},
watch: {
'id': 'routeChanged',
},
methods: {
routeChanged () {
console.log(this.id);
},
},
};
</script>
I am getting below error:
[Vue warn]: Invalid prop: type check failed for prop "id". Expected Number, got String.
That is the use case for Passing Props to Route Components with Function mode:
You can create a function that returns props. This allows you to cast parameters into other types, combine static values with route-based values, etc.
In your case, instead of specifying the route option with props: true, you would pass a function to the props option:
routes = [{
path: '/word/:id',
component: Word,
props: castRouteParams
}];
function castRouteParams(route) {
return {
id: Number(route.params.id),
};
}
Live example: https://codesandbox.io/s/8kyyw9w26l (click on the "Go to Test/3" link)