簡體   English   中英

雙向數據綁定不適用於Angular.js中的指令

[英]Two-way data binding does not work with directives in Angular.js

我嘗試實現一個指令,它必須使用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}}在控制器中實現。

謝謝您的幫助!

要動態編譯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

請注意,只要您不自行使用$ compile,AngularJS模板只會在應用程序引導期間編譯一次。

AngularJS編譯和鏈接階段

要了解代碼無法正常工作的原因,您必須了解AngularJS編譯和鏈接階段。 加載應用程序后,AngularJS將編譯包含帶有$ compile服務的ng-app屬性的HTML元素,例如

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

編譯階段

$ compile標識HTML模板中的所有指令,調用每個指令的編譯函數從角度根元素($ rootElement)到html dom樹。

鏈接階段

每個編譯函數返回一個帖子鏈接和可選的預鏈接函數。 一旦AngularJS在根元素下面編譯了整個dom,它就會以之前調用編譯函數的方式開始調用預鏈接函數。 一旦到達dom的葉子,指令的post-link函數就會被調用回到根元素。

插值

具有{{和}}之間表達式的字符串由AngularJS作為稱為插值指令的特殊指令處理。 正如使用$ interpolate服務在編譯期間創建的任何其他指令一樣。 $ interpolate服務接收帶有多個表達式的內部字符串,並返回一個內部板函數。 插值指令的post-link函數在插值函數上創建監視,以便一旦插入的字符串中的任何表達式發生更改,它們就可以更新html節點。

翻譯模塊

當我們現在查看您的代碼時,您實際上是將一個html元素的文本設置為一個AngularJS插值字符串,其中一個表達式在指令的post-link函數中包含在{{和}}之間。

如上所述,此時AngularJS已經編譯了模板,因此它永遠不會使用您的表達式編譯插值字符串。

正如我從您的代碼中看到的那樣,您正在嘗試實現某種translate指令。 當它應該在翻譯的字符串中考慮插值字符串和其他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/

另外,對於翻譯,我建議http://github.com/pascalprecht/angular-translate

我認為$compile可能就是你想要的。 嘗試:

var bindLabel = $compile('{{labels.' + element.text() + '}}')(scope);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM