2

angular-notation {{...}} で特定のコード ブロックを更新する必要があるディレクティブを実装しようとしています。問題は、更新されたコードがコンパイルされていないことです。

ディレクティブ:

.directive('i18n', [function() {
'use strict';
return function(scope, element) {
        var bindLabel = '{{labels.' + element.text() + '}}',
        //create an empty object
        obj = {

        };
        obj[element.text()] = '';
        //extend the labels
        angular.extend(scope.labels, obj);
        element.text(bindLabel);
};
}])

簡単な HTML コード:

<title i18n>title</title>

コンパイル後の HTML コード:

<title i18n="">{{labels.title}}</title>

望ましい出力:

 <title i18n="">This is my title :)</title>

{{labels.title}}コントローラに実装されています。

ご協力ありがとうございました!

4

4 に答える 4

8

DOM 要素を動的にコンパイルするには、次の$compileサービスを使用します。

element.html(value);

// Compile the new DOM and link it to the current scope

$compile(element.contents())(scope);

あなたの例の場合、次のようになります。

.directive('i18n', [ '$compile', function($compile) {
'use strict';
return function(scope, element) {
        var bindLabel = '{{labels.' + element.text() + '}}',
        //create an empty object
        obj = {

        };
        obj[element.text()] = '';
        //extend the labels
        angular.extend(scope.labels, obj);

        // Fill element's body with the template

        element.html(bindLabel);

        // Compile the new element and link it with the same scope

        $compile(element.contents())(scope);
    };
}]);

詳細については、http: //docs.angularjs.org/api/ng.$compileをご覧ください。

于 2013-05-21T17:31:01.087 に答える
5

$compile を独自に使用しない限り、アプリケーションのブートストラップ中に AngularJS テンプレートが 1 回しかコンパイルされないことに注意してください。

AngularJS のコンパイルとリンクのフェーズ

コードが機能しない理由を理解するには、AngularJS のコンパイルとリンクのフェーズを理解する必要があります。アプリケーションをロードすると、AngularJS は ng-app 属性を含む HTML 要素を $compile サービスでコンパイルします。

<html ng-app="MyApp"></html>

コンパイル段階

$compile は、各ディレクティブのコンパイル関数を呼び出す HTML テンプレート内のすべてのディレクティブを識別し、Angular ルート要素 ($rootElement) から html dom ツリーを介して上に向かって動作します。

リンクフェーズ

各コンパイル関数は、リンク後の関数と、オプションでリンク前の関数を返します。AngularJS がルート要素の下の dom 全体をコンパイルすると、以前にコンパイル関数を呼び出したのと同じ方法で、リンク前関数の呼び出しが開始されます。dom のリーフに到達すると、ディレクティブのリンク後関数が呼び出され、ルート要素に戻ります。

補間

{{ と }} の間の式を含む文字列は、補間ディレクティブと呼ばれる特別なディレクティブとして AngularJS によって処理されます。他のディレクティブと同様に、これらは $interpolate サービスを使用してコンパイル中に作成されます。$interpolate サービスは、多数の式で補間された文字列を受け取り、補間関数を返します。補間ディレクティブのリンク後関数は、補間関数にウォッチを作成し、補間された文字列の式が変更されたときに html ノードを更新できるようにします。

翻訳モジュール

コードを見ると、ディレクティブのポストリンク関数で {{ と }} で囲まれた式を使用して、HTML 要素のテキストを AngularJS 補間文字列に実際に設定しています。

上記で説明したように、この時点で AngularJS は既にテンプレートをコンパイルしているため、補間された文字列を式でコンパイルすることはありません。

コードからわかるように、ある種の変換ディレクティブを実装しようとしています。そのようなディレクティブは、翻訳された文字列で補間された文字列と他の AngluarJS テンプレート コードを考慮する必要がある場合、 $compile 関数を呼び出す必要があります。

directive('translate', ['$compile','translate', function factory($compile, translate) { 
    return {            
        priority: 10, // Should be evaluated before e. g. pluralize
        restrict: 'ECMA',
        link: function postLink(scope, el, attrs) {
            if (el.contents().length) {
                el.html(translate(el.text()));
                $compile(el.contents())(scope); // This is only necessary if your translations contain AngularJS templates
            }
        },
    };
}]).

translate ディレクティブは、翻訳サービスを使用して実際の翻訳を取得します。translateProvider には、言語バンドルなどから翻訳を追加するために使用できる add メソッドがあります。

.provider('translate', function() {
    var localizedStrings = {};
    var translateProvider = this;
    this.add = function(translations) {
        angular.extend(localizedStrings, translations);
    };
    this.$get = ['$log', '$rootScope', function ($log, $rootScope) {
        var translate = function translate(sourceString) {            
            if (!sourceString) {
                return '';
            }
            sourceString = sourceString.trim();
            if (localizedStrings[sourceString]) {
                return localizedStrings[sourceString];
            } else {
                $log.warn('Missing localization for "' + sourceString + '"');
                return sourceString;
            }
        };
        return translate;
    }];    
}).
config(function(translateProvider) {
    translateProvider.add({'My name is {{name}}': 'Mi nombre es {{name}}'}); // This might come from a bundle
}).

モジュールの使用

モジュールを次のように使用できるようになりました。

<div ng-app="myApp" ng-controller="MyCtrl">
    <span data-translate>My name is {{name}}</span>
</div>

完全な例でjsFiddleを作成しました:http://jsfiddle.net/jupiter/CE9V4/2/

于 2013-05-21T18:25:40.457 に答える
2

さらに、翻訳にはhttp://github.com/pascalprecht/angular-translateをお勧めします。

于 2013-05-22T00:19:48.000 に答える
0

私は$compileあなたが探しているものかもしれないと思います。試す:

var bindLabel = $compile('{{labels.' + element.text() + '}}')(scope);
于 2013-05-21T17:26:19.663 に答える