【问题标题】:Angular 5 - ngx-translate within routerLinkAngular 5 - routerLink 中的 ngx-translate
【发布时间】:2018-10-16 00:13:09
【问题描述】:

在我的项目(Angular 5 + Firebase)中,用户需要在登录页面选择语言。为此,我添加了选择选项并将选择的值作为参数传递给第一页,如下所示:

form_login(f:NgForm){
    if (!f.valid)
      return;
    this.afAuth.auth.signInWithEmailAndPassword(f.controls.email.value, f.controls.password.value)
      .then(ok => {     
        this.router.navigate(["/perfil", f.controls.lang.value]); //>> here
      });
  }

在 url 中有这个参数,我检索这个值并使用 ngx-translate 来翻译整个页面,如下所示:

perfil.component.ts

import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';

constructor(private translate: TranslateService,  
    private route: ActivatedRoute, 
    private router: Router) { 

      ...
      translate.setDefaultLang('en');

      let lang = this.route.snapshot.paramMap.get('lang');
      this.translate.use(lang);
      console.log(lang);
    }

perfil.component.html

<h5 translate>Companyprofile</h5>

完美运行。除了因为还有一个导航栏,而且这个组件根本没有获取语言值。虽然翻译了链接标签,但每个routerLink的值并没有捕捉到参数的值,而是将每个链接设置为undefined,其中应该是语言的值。

navbar.component.ts

import { Router, ActivatedRoute, ParamMap } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';

constructor(private translate: TranslateService,  
    private route: ActivatedRoute, 
    private router: Router) { 

      ...
      translate.setDefaultLang('en');

      let lang = this.route.snapshot.paramMap.get('lang');
      this.translate.use(lang);
      console.log(lang); // >> in this case, the console displays `null`
    }

尝试在 navbar.component.ts 上获取此值,我在控制台上出现此错误:

navbar.component.ts:36 null
zone.js:2935 GET http://localhost:4200/assets/i18n/null.json 404 (Not Found)

core.js:1440 ERROR HttpErrorResponse {headers: HttpHeaders, status: 404, statusText: "Not Found", url: "http://localhost:4200/assets/i18n/null.json", ok: false, …}

navbar.component.html

 <header id="topnav">
   <ul class="navbar-nav" *ngFor="let p of perfil | async">
     <li class="nav-item">
       <a [routerLink]="['/agenda/', lang]" class="nav-link" translate>Agenda</a>
     </li>
     <li class="nav-item">
       <a [routerLink]="['/admin/', lang]" class="nav-link" translate>Admin</a>
     </li>
   ...
   </ul>
 </header>
 <router-outlet></router-outlet> <!-- here I call other components, e.g perfil.component.html

例如,lang 参数应带值 'en'。但是,相反,它是undefined

编辑:我所有的组件都是NavbarComponent 的子组件。 NavbarComponent 没有path,所以不能像我在其他路径中那样设置参数。

app.routing.module.ts

const AppRoutes: Routes = [

    {path: '', component: AppComponent, children: [
        { path: '', redirectTo: '/login', pathMatch: 'full' },
        {path: '', component: NavbarComponent, children: [
            {path: 'agenda/:lang', component: AgendaComponent},
            {path: 'perfil/:lang', component: PerfilComponent},
            {path: 'servicos/:lang', component: CadastroServicoComponent},
            {path: 'profissionais/:lang', component: ProfissionaisComponent},
            {path: 'admin/:lang', component: AdminComponent},
            {path: 'dashboard/:lang', component: DashboardComponent},
            {path: 'signup/:lang', component: SignUpFormComponent}
        ]}
    ]}
]    

@NgModule({
imports: [RouterModule.forRoot(AppRoutes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

代码有什么问题?

【问题讨论】:

  • 如果我没看错的话,您正在使用lang 变量在navbar.component.html 内创建routerLink。您是否在navbar.component.ts 文件中的某处设置了此变量?因为在您的代码中,我只能在 perfil.component.ts 文件中找到 lang 变量。
  • 是的,我也在 navbar.component.ts 内部使用。在这种情况下,我已经编辑了我的问题并添加了关于 console.log 的评论。谢谢!

标签: javascript angular routes ngx-translate routerlink


【解决方案1】:

好的,这是基于我从代码中看到的建议。

您的导航栏可能在您的一个组件中作为子组件被调用,可能就像在您的perfil.component.html 中一样。

<navbar [parameters...]></navbar>

我对此不是 100% 确定,但我猜ActivatedRoute 注入仅适用于通过直接路由器链接加载的组件,不适用于子模块(我真的不确定) .这意味着AcitvatedRoute 适用于perfil.component,但不适用于navbar.component(因为没有从您的路由器调用)。但是,如果您的导航栏的调用方式如上所示,您可以将lang 变量从perfil.component 发送到导航栏作为输入参数。

这是perfil.component.html

<navbar [lang]="lang"></navbar>

这是navbar.component.ts

// the lang string is now an input parameter
@Input() lang: string;

constructor(private translate: TranslateService, private router: Router) { 
  ...
  // the default language should already been set in the parent component
  // NO NEED: translate.setDefaultLang('en');
}

// the input parameter are not yet availbable in the constructor, but on init
ngOnInit(){
  this.translate.use(lang);
  console.log(lang);
}

希望这会有所帮助。


编辑

看到你的命令后,我发现导航栏出了什么问题。您的导航栏组件是第一个被调用的组件,可以说是父组件,在子组件初始化之前构建。

问题是导航栏有自己的当前路线。您要做的是访问父组件中的子路由。我发现了一个类似的问题here,其答案似乎不再有效。如有必要,您可以检查一下,还有另一种解决方案,虽然它看起来很棘手。所以我不确定这是否是要走的路。

改进建议

我看到的问题是使用语言作为 child 组件而不是 parent 组件的路由参数的方法本身。该语言目前是在导航栏的每个子路由上设置的路由参数,导致代码中出现大量重复。无论如何,所有孩子肯定都必须经过导航栏初始化过程,那么为什么不在那里处理语言的东西呢?这样,您只需在代码中的一处进行语言加载。

在这种情况下你可能需要调整你的路由器,像这样。

    { path: '', redirectTo: '/login', pathMatch: 'full' },
    { path: ':lang', component: NavbarComponent, children: [
        {path: 'agenda', component: AgendaComponent},
        {path: 'perfil', component: PerfilComponent},
        {path: 'servicos', component: CadastroServicoComponent},
        {path: 'profissionais', component: ProfissionaisComponent},
        {path: 'admin', component: AdminComponent},
        {path: 'dashboard', component: DashboardComponent},
        {path: 'signup', component: SignUpFormComponent}
    ]}

目前不工作的代码也不再需要,因为您不必再​​为子路由指定语言。

<header id="topnav">
   <ul class="navbar-nav" *ngFor="let p of perfil | async">
     <li class="nav-item">
       <!-- without / the router routes to children relative to the current path -->
       <!-- no need for the language anymore -->
       <a [routerLink]="['agenda']" class="nav-link" translate>Agenda</a>
     </li>
     <li class="nav-item">
       <a [routerLink]="['admin']" class="nav-link" translate>Admin</a>
     </li>
   ...
   </ul>
 </header>

从您的登录页面,您直接路由到/lang 页面(即导航栏),然后在那里初始化语言(并且只执行一次)。所有子组件现在都是 lang 路由的子组件,而不是拥有自己的 lang 参数。在navbar.component.ts 中,您可能可以使用您当前使用的完全相同的代码。并且在子组件中,不再初始化ngx-translate,它现在集中在父组件中。如果您想在其中一个子组件中使用语言参数,您仍然可以在那里访问当前路由,因为该参数仍然是路由的一部分,只是位于更左侧。

希望这足够准确。

【讨论】:

  • 感谢您的回答。事实上,情况恰恰相反。我重新编辑了navbar.component.html 代码,因此您可以看到其他组件已加载到导航栏下方。如果你在路由代码中看到app.routing.module.ts,你会注意到PerfilComponentNavbarComponent的孩子,而后者没有路径,所以不可能在路由配置中包含参数。
  • 我已经用新的解决方案更新了答案。我个人认为整个问题都来自一个应该可以很快调整的设计问题。只需将 lang 参数从所有子组件切换到父组件,就可以了。
  • 在您更新后,我尝试遵循您的建议。但是,不幸的是,他们还没有成功。现在,不是从login 页面开始,而是第一页是navbar(下面没有任何内容),但URL 是http://localhost:4200/login。此外,现在链接是使用登录作为其父路由构建的,例如http://localhost:4200/login/agenda
  • 如果我理解正确,您的登录页面在您的正常页面之前,因此您将使用空路径的初始调用重定向到您的登录页面。所以第一页应该没问题。从那里开始,登录本身(您选择语言的位置)之后,您必须在内部重定向(例如登录操作中的路由器调用)到导航栏链接,这当然只有在您从登录页面获取语言参数。您的路由器中没有登录路由,您是否已经在选择语言的地方完成了登录?
  • 是的,有登录路由({ path: '', redirectTo: '/login', pathMatch: 'full' },使登录成为“/”导航时打开的页面)和登录页面(请看代码的第一个sn-p我发布了,在那里我对用户进行身份验证并检索他们选择的语言)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多