I'm doing multi-language support with vue js, everything works fine, but when I change the language, the data in the data
menuItem name does not change.
Vuei18n
<template v-slot:MenuItem>
<MenuItems v-for="(Item,Index) in menuItem"
:key="Index"
:items="Item"
:depth="Index"
>
<router-link :to="Item.path">{{Item.name}}</router-link>
</MenuItems>
</template>
export default {
name: "Nav",
data() {
return {
menuItem: [
{
name: this.$t('navbar.home'),
path: '',
},
{
name: this.$t('navbar.gallery'),
path: 'gallery',
},
{
name: this.$t('navbar.contact'),
path: 'contact',
},
],
}
}
}
data() is only called once when creating the component, and it's not intended to be reactive.
(So basically when your component is being created, it gets the your current translation as initial values)
To make a property reactive on $t(), you should use computed var instead:
export default {
name: "Nav",
data() {
// exclude from here
return {};
},
computed: {
menuItem() {
return [
{
name: this.$t("navbar.home"),
path: "",
},
{
name: this.$t("navbar.gallery"),
path: "gallery",
},
{
name: this.$t("navbar.contact"),
path: "contact",
},
];
},
},
};
Related
I want to send data from home component via book.vue router link, but I am getting an error. Where am I doing wrong?
Home.vue
export default {
data() {
return {
data: {
attributes: {
name: 'Jonh',
age: '25',
},
},
}
},
}
router/index.js:
const routes = [
{ path: '/Library/:id', name: 'Book', component: Book, props: true },
]
navigation:
:to="{ name: 'Book', params: { id: book.id}, props: { data: data.attributes} }"
Book.vue
export default {
props: {
id: {
type: Array,
required: true
}
}
}
This is how I passed the prop:
<router-link :to="{ name: 'Cart', params: { payment_method: 'cod' } }">
Router component is like this:
{
path: "/cart",
name: "Cart",
component: Cart,
props: true,
meta: {
requiresAuth: true,
},
},
in the receiving route, Props:
props: {
payment_method: String,
},
I am getting undefined as value for payment_method. what is wrong here?
Change your router component path to:
{
path: "/cart/:payment_method",
name: "Cart",
component: Cart,
props: true,
meta: {
requiresAuth: true,
},
},
Try to set payment_method as slug in route with props:true and catch the route's prop directly in data of vue instance
<router-link :to="{ name: 'Cart', params: { payment_method: 'cod' } }">
{
path: "/cart/:payment_method",
name: "Cart",
component: Cart,
props: true,
meta: {
requiresAuth: true,
},
},
catch directly in data
data: function () {
return {
payment_method: this.$route.params.payment_method,
};
},
This will resolve your problem
In Vue JS3, my Vue component, I can pass props like this: Parent:
<script>
export default {
data() {
return {
links: [],
};
},
methods: {
editLink(el) {
this.$router.push({
name: "EditLink",
params: {
id: el.id,
short_link: el.short_link,
long_link: el.long_link,
},
});
},
},
};
</script>
Component:
<script>
export default {
props: ["elem"],
data() {
return {
link: {},
};
},
mounted() {
this.link = {
id: this.$route.params.id,
short_link: this.$route.params.short_link,
long_link: this.$route.params.long_link,
};
},
};
</script>
But If I pass the Object named el directly like this:
this.$router.push({
name: "EditLink",
params: {
elem: el,
},
});
When I try to print it out, I get the value of elem as [Object Object], instead of an actual object. Why is this happening? What's the solution?
Try out to spread the el instead of assigning each value to the respective key :
this.$router.push({
name: "EditLink",
params: {...el},
});
then in the target page :
mounted() {
this.link = {...this.$route.params};
},
I am having a problem where my parent component (LoggedInComponent) is getting reloaded every time one of the child components changes (child route change).
I have searched high and low for an answer but can't seem to find anything suitable to my situation.
Here is my app-routing.module.ts
const routes: Routes = [
{ path: 'login', component: LoginComponent },
{
path: '', component: LoggedInComponent, canActivateChild: [AuthGuard], children: [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
{ path: 'home', component: DashboardComponent },
{ path: 'groups', component: GroupsComponent, data: { role: [PermissionEnum.Groups_View] } },
{ path: 'groups/edit/:id', component: GroupDetailComponent, data: { role: [PermissionEnum.Groups_Edit] } },
{ path: 'groups/create', component: GroupDetailComponent, data: { role: [PermissionEnum.Groups_Create] } },
{ path: 'users', component: UsersComponent, data: { role: [PermissionEnum.Users_View] } },
{ path: 'users/edit/:id', component: UserDetailComponent, data: { role: [PermissionEnum.Users_Edit] } },
{ path: 'users/create', component: UserDetailComponent, data: { role: [PermissionEnum.Users_Create] } },
{ path: 'profile', component: ProfileComponent },
{ path: 'profile/:tabindex', component: ProfileComponent },
{ path: 'settings', component: SettingComponent, data: { role: [PermissionEnum.Global_Settings_View] } },
{ path: 'external-login/:result', component: ExternalLoginProvidersComponent },
{ path: 'permissions/:id/:type', component: PermissionsComponent, data: { role: [PermissionEnum.Users_AssignPermissions] } },
{ path: 'permission-denied', component: PermissionDeniedComponent },
{ path: 'reference-data/:type', component: ReferenceDataComponent, data: { role: [PermissionEnum.Sms_Template_View] } },
{ path: 'reference-data/:type/edit/:id', component: ReferenceDataDetailsComponent, data: { role: [PermissionEnum.Sms_Template_Edit] } },
{ path: 'reference-data/:type/create', component: ReferenceDataDetailsComponent, data: { role: [PermissionEnum.Sms_Template_Create] } },
{ path: 'tenants', component: TenantsComponent, data: { role: [PermissionEnum.Tenant_View] } },
{ path: 'tenants/edit/:id', component: TenantDetailComponent, data: { role: [PermissionEnum.Tenant_Edit] } },
{ path: 'tenants/create', component: TenantDetailComponent, data: { role: [PermissionEnum.Tenant_Create] } },
{ path: 'sms-campaigns', component: SmsCampaignsComponent, data: { role: [PermissionEnum.SmsCampaign_View] } },
{ path: 'sms-campaigns/create', component: CreateSmsCampaignComponent, data: { role: [PermissionEnum.SmsCampaign_Create] } },
{ path: 'sms-campaigns/details/:id', component: SmsCampaignDetailsComponent, data: { role: [PermissionEnum.SmsCampaign_View] } },
{ path: 'document-library', component: LibraryDocumentsComponent },
{ path: 'report-management', component: ReportManagementComponent },
{ path: 'report-management/create', component: CreateReportComponent },
{ path: 'report-management/:id', component: IdpComponent },
{ path: 'report-management/edit/:id', component: ReportDetailsComponent },
{ path: 'report/:reportName', component: ReportComponent }
]
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
I have the main router-outlet in my app.component.html which after loggin in takes you to the LoggedInComponenet which has the header, footer, left menu and another router-outlet for the children.
This is my LoggedIn.componenent.html
<app-header></app-header>
<div class="m-grid__item m-grid__item--fluid m-grid m-grid--ver-desktop m-grid--desktop m-body">
<app-left-menu></app-left-menu>
<div *ngIf="loading">
<app-loading-indicator></app-loading-indicator>
</div>
<div class="center-display" *ngIf="childrenLoadingAllowed">
<router-outlet class="m-grid__item m-grid__item--fluid m-wrapper" [ngClass]="{ hidden: loading }"></router-outlet>
</div>
</div>
<app-footer></app-footer>
I then have my LoggedIn.component.ts
import { Component, OnInit } from '#angular/core';
import { BaseComponent } from '../shared/base.component';
#Component({
selector: 'app-logged-in',
templateUrl: './logged-in.component.html',
styleUrls: ['./logged-in.component.css']
})
export class LoggedInComponent extends BaseComponent implements OnInit {
public loading = true;
public childrenLoadingAllowed = false;
constructor() {
super();
}
ngOnInit() {
this.layoutService.setLoadingEvent
.subscribe((res: boolean) => {
if (this.loading !== res)
this.loading = res;
});
}
}
And then finally here is the left-menu which keeps reloading when i load a child
import { Component, OnInit, ViewEncapsulation } from '#angular/core';
import { BaseComponent } from '../../shared/base.component';
import { PermissionEnum, LookupClient, LookupType, LookUpDto } from '../../../services/web-api-generated';
#Component({
selector: 'app-left-menu',
templateUrl: './left-menu.component.html',
styleUrls: ['./left-menu.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class LeftMenuComponent extends BaseComponent implements OnInit {
public hasReports = false;
public reports: Array<LookUpDto> = new Array<LookUpDto>();
constructor(private lookupClient: LookupClient) {
super();
this.loadReportMenuItems();
}
ngOnInit() {
this.layoutService.rebuildReportMenu
.subscribe(res => {
this.loadReportMenuItems();
});
}
private loadReportMenuItems(): void {
this.lookupClient.getLookUpValues(LookupType.MunicipalReports)
.subscribe((res: Array<LookUpDto>) => {
this.reports = res;
this.reports.forEach(element => {
element.value = element.value.replace(/\s+/g, '-').toLocaleLowerCase();
});
this.hasReports = res.length > 0;
});
}
}
I fixed the problem by moving the api call to a service with a variable there and only loading the data if its not already set or if the force variable is passed through.
I believe this is a bug as mentioned here: https://github.com/angular/angular/issues/18374
yes, canActivateChild reloads whole parent component while changing between child routes
I have the following routes in my VueJS app:
const routes = [
{
path: '/',
component: PlacesList
},
{
name: 'place',
path: '/places/:name',
component: CurrentWeather,
children: [
{
name: 'alerts',
path: 'alerts',
component: ForecastAlerts
},
{
name: 'forecast',
path: 'forecast',
component: ForecastTimeline
}
]
}
];
ForecastTimeline receives props passed from CurrentWeather:
export default {
name: 'ForecastTimeline',
props: ['forecastData'],
components: {
ForecastDay
}
}
When I navigate to /places/:name/forecast from /places/:name everything works well. However, when I try to reach /places/:name/forecast directly I get a Cannot read property 'summary' of undefined error. This occurs because forecastData is fetched asynchronously within the CurrentWeather component. What is the proper way to handle asynchronous properties passed to a nested route?
Have you tried not displaying the subroutes components while fetching the data ?
Something like :
export default {
name: 'CurrentWeather',
data(){
return {
loading: true
}
},
created(){
this.fetchForecastData().then(() => {
this.loading = false;
});
},
methods: {
fetchForecastData() {
return fetch('http://..');
}
}
}
In CurrentWeather template :
<router-view v-if="!loading"></router-view>