【问题标题】:Use AngularJS 2 Component like a function in the element attribute在元素属性中像函数一样使用AngularJS 2组件
【发布时间】:2016-11-02 12:04:24
【问题描述】:

大家好!

我正在学习 AngularJS 2 一段时间,现在基于 Laravel 5 REST API 创建自己的应用程序。无论如何 - 这不是很重要的atm。

重要的是我想为整个应用程序提供翻译,但我发现了一个对我来说很难解决的问题。

所以 - 从一开始...我创建了用于翻译字符串的 ResourcesService

getTranslation ( key: string, replace: Array<TranslationReplace> = null, locale: string = null, fallback: boolean = null ): Observable<Resource> {

    var params = "key=" + key +
        ( replace ? "&replace=" + JSON.stringify(replace) : '') +
        ( locale ? "&locale=" + locale : '') +
        ( fallback ? "&fallback=" + fallback : '');
    var headers = new Headers({'Content-Type':'application/x-www-form-urlencoded'});

    return this.http.post(this.apiUrl + 'getTranslation', params, {headers: headers})
        .map(this.extractData)
        .startWith({ name: 'Loading...', value: 'Translating...' })
        .catch(this.handleError);

}

我创建了一个 TranslateComponent 来提供翻译,这是整个组件:

import {Component, Input, Injectable, OnInit, OnChanges, SimpleChange} from "@angular/core";
import {ResourcesService} from "../services/resources.service";
import {TranslationReplace} from "../models/TranslationReplace";

@Component({
    selector: 'translate',
    template: `{{translation}}`
})

@Injectable()
export class TranslateComponent implements OnInit, OnChanges {

    @Input() ref: string;
    @Input() replace: Array<TranslationReplace>;
    @Input() locale: string;
    @Input() fallback: boolean;

    private translation: string;
    constructor(private resourcesService: ResourcesService) {}

    ngOnInit() : void {
        this.getTranslation();
    }

    ngOnChanges(changes: {[propKey: string]: SimpleChange}) {
        for (let propName in changes) {
            if(propName == 'replace') {
                this.getTranslation();
            }
        }
    }

    private getTranslation(): void {
        this.resourcesService.getTranslation(this.ref, this.replace, this.locale, this.fallback).forEach(translation => this.translation = translation.value );
    }
}

一切都完美无缺,要调用翻译,我必须像这样简单地调用选择器:

<translate [ref]="'string.to_translate'"></translate>

但是……

现在我想在属性中使用翻译。

所以我找到了通过创建翻译的引用并在属性中调用它来实现它的丑陋方法。但是很恶心……

首先我需要将这一位添加到我的模板中:

<translate [ref]="'string.to_translate'" style="display:none;" #myStringTranslation></translate>

接下来在我的元素中调用它并通过引用请求属性:

<input type="text" [(ngModel)]="input" #input="ngModel [placeholder]="myStringTranslation.translation">

我真的不喜欢这个主意。

我正在寻找的是以某种方式调用它,我不知道......发出它?并让它看起来更好。不要创建额外的元素。

所以我的问题是: 我可以做得更好吗?我可以在没有引用的情况下直接从属性调用翻译吗?

** ----- 更新 ----- **

好的,我吸取了教训 :) 感谢 Meir 向我展示了正确的方向以及 Angular.io 网站的教程。

所以最后我在我的应用程序中添加了一个 TranslateDirective

import {Directive, Input, ElementRef, OnChanges, OnInit, SimpleChange, Renderer} from "@angular/core";
import {TranslationReplace} from "../models/TranslationReplace";
import {ResourcesService} from "../services/resources.service";

@Directive({
    selector: '[translate]'
})
export class TranslateDirective implements OnInit, OnChanges {

    @Input('translate') ref: string;
    @Input('translateReplace') replace: Array<TranslationReplace>;
    @Input('translateLocale') locale: string;
    @Input('translateFallback') fallback: boolean;
    @Input('translateAttr') attr: string;

    private translation: string;

    constructor(
        private elRef: ElementRef,
        private renderer: Renderer,
        private resourcesService: ResourcesService
    ) {}

    ngOnInit():void {
        this.getTranslation();
    }

    ngOnChanges(changes: {[propKey: string]: SimpleChange}):void {
        for (let propName in changes) {
            if(propName == 'replace') {
                this.getTranslation();
            }
        }
    }

    private getTranslation(): void {
        if(this.attr)
            this.resourcesService.getTranslation(this.ref, this.replace, this.locale, this.fallback).forEach(translation =>
            {
                this.translation = translation.value;
                this.renderer.setElementAttribute(this.elRef.nativeElement,this.attr,this.translation);
            });
    }
}

现在可以像这样轻松地将翻译添加到属性中:

<input type="text" [(ngModel)]="input" #input="ngModel [translate]="'string.to_translate'" [translateAttr]="'placeholder'">

感谢您的帮助!!

【问题讨论】:

  • 没有'AngularJS 2',这个名字适用于Angular 1.x。

标签: javascript angular frontend


【解决方案1】:

你可以把它变成一个属性指令:

@Directive({
  selector: 'translate'
})
export class TranslateDirectiev {
  @Input() translate: string;

  constructor(private elRef: ElementRef){}

  ngOnChanges(changes: SimpleChanges): void {
       if(this.translate){
          var translatedText: string = translateSvc.translate(this.translate);
          this.renderer.setElementProperty(this.elementRef.nativeElement, 'innerHTML', translatedText);
      }
  }

}

这是一个没有服务注入的简单示例。此外,对于输入字段,您可能需要采用不同的方法并更新 value 属性而不是 innerHtml

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-24
  • 1970-01-01
  • 2019-01-06
  • 2020-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多