Угловой 5 - ngx-translate внутри routerLink - PullRequest
0 голосов
/ 05 мая 2018

В моем проекте (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 { }

Что не так с кодом?

1 Ответ

0 голосов
/ 05 мая 2018

Хорошо, вот предложение, основанное на том, что я вижу из кода.

Ваш navbar, вероятно, вызывается внутри одного из ваших компонентов как дочерний компонент, возможно, так же, как внутри вашего 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);
}

Надеюсь, это поможет.


EDIT

Увидев вашу команду, я вижу, что у меня не так с навигацией. Ваш компонент navbar вызывается первым, так сказать, родительским компонентом, который создается до инициализации потомков.

Проблема в том, что у navbar есть свой текущий маршрут. То, что вы пытаетесь сделать, это получить доступ к дочернему маршруту в родительском компоненте. Я нашел похожий вопрос здесь с принятым ответом, который, кажется, больше не работает. Вы можете проверить это при необходимости, есть другое решение, хотя это выглядит сложно. Так что я не уверен, что это путь.

Предложение по улучшению

Проблема, которую я вижу, заключается в самом подходе с языком в качестве параметра маршрутизации для дочерних компонентов, а не для parent . Язык в настоящее время является параметром маршрута, который устанавливается на каждом дочернем маршруте панели навигации, что приводит к большому повторению в вашем коде. В любом случае, все дети обязательно должны пройти процесс инициализации navbar, так почему бы не поработать над языком? Таким образом, вам нужно только выполнить языковую загрузку в одном месте вашего кода.

В этом случае вам, вероятно, придется настроить роутер, что-то вроде этого.

    { 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, теперь он централизован в родительском компоненте. Если вы хотите использовать языковой параметр в одном из дочерних компонентов, вы все равно можете получить доступ к текущему маршруту там, потому что параметр все еще является частью маршрута, он просто расположен немного левее.

Надеюсь, это достаточно точно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...