指令与服务之间的沟通

时间:2020-03-12 07:19:09

标签: angular

我正在尝试在我的项目中开发国际化而不使用第三方模块来解决这个问题。这是我的翻译服务:

export class TranslationService {
    private translations: any;

    // load translations for the certain language
    loadTranslations(lang: string) { ... }

    // get translation by key
    get(key: string) {
        return this.translations[key];
    }

}

这是我的指令,它将替换标记中的文本:

export class I18nDirective implements OnInit {
    @Input() i18n: string;

    constructor(private el: ElementRef,
                private translationService: TranslationService) {}

    ngOnInit() {
        this.el.nativeElement.textContent = this.translationService.get(this.i18n);
    }

}

示例:<div i18n="global.welcome">This text will be replaced</div>

问题::当前,更改语言将触发TranslationService加载新的翻译,但指令对此一无所知。我应该如何“询问”指令以使用新的翻译并将其替换为文本?

1 个答案:

答案 0 :(得分:1)

我想您可以在TranslationService中创建一个Subject,并订阅指令,例如

export class TranslationService {
    private subject = new Subject<any>();
    public observable=this.subject.asObservable();

    loadTranslations(lang: string) { 
      ... 
   this.subject.next(true)
    }
   ...
}

export class I18nDirective implements OnInit {
    @Input() i18n: string;

    constructor(private el: ElementRef,
                private translationService: TranslationService) {}

    ngOnInit() {
        this.translationService.observable.pipe(
           startWith(null)
        ).subscribe(()=>{
           this.el.nativeElement.textContent = this.translationService.get(this.i18n);
        })
    }

}

其他选择是在指令中创建方法setValue

setValue()
    {
        this.el.nativeElement.textContent = this.translationService.get(this.i18n);
    }

然后在您的组件中使用ViewChildren获取指令

@ViewChildren(I18nDirective) labels: QueryList<I18nDirective>;

改变成语时

changeIdioma() {
    this.translationService.loadTranslations(this.idioma).subscribe(()=>{
      this.labels && this.labels.forEach(x => x.setValue());
    })
  }

您可以在stackblitz(*)

中看到

(*)我提出了两种方式,只是没有出现这些行