使数据模板化为ng-model可用

时间:2013-01-23 21:18:19

标签: angularjs

当使用服务器端模板和客户端angularjs时,我无法获得angularjs来识别我在服务器上模板化的值。

例如(或on jsfiddle):

<div ng-app>
<div ng-controller="Ctrl">
    <textarea ng-model="data" placeholder="Enter a name here">Templated in</textarea>
    {{data}}
</div>
</div>

Angularjs将始终使用$scope.data的值(为空)替换文本区域中的值。我想要的是$scope.data的值在“模板化”中,在应用程序引导程序上,然后从那里正常继续。

如何从服务器模板输入值,然后让angularjs模型在客户端上绑定该值一次?

2 个答案:

答案 0 :(得分:4)

使用ng-init

<textarea ng-model="data" placeholder="Enter a name here"
 ng-init="data='Templated in'"></textarea>

另见AngularJS - Value attribute on an input text box is ignored when there is a ng-model used?
rails + angularjs loading values into textfields on edit

答案 1 :(得分:2)

我在试图为自己解决这个问题时遇到了这个问题,但从未喜欢过我必须从HTML规范所需的字段中移动信息。这对我来说感觉不对。

有一段时间,我最终利用了Angular坐在jQuery(或嵌入式jqLit​​e子集,如果没有完整的jQuery)的基础上解决这个问题而不移动内容,甚至触及ng-在里面。具体来说,您可以在控制器初始化阶段使用(Angular/jqLite versionstandard jQuery methods访问textarea的内容。

所以我刚刚做了

var doc = angular.element(document.documentElement);

$scope.data = doc.find('textarea').eq(0).val();

在我的控制器中,我将初始化任何其他范围变量。 (或者,这是modified jsFiddle ...)

使用完整的jQuery库,代码更简单,因为此时您可以访问完整的jQuery selectors并且可以直接跳转到$('textarea').eq(0).val()(甚至可以向字段添加id和选择:$('#data-textarea').val())。

这种方法的优点在于它适用于任何表单元素,但由于大多数都是<input>标记,而jqLit​​e不支持选择器,因此找到所需的确切元素可能有点棘手。我只想在那时包含完整的jQuery库并利用选择器,但那就是我。

这种方法的主要缺点是将DOM感知代码放在控制器中,这完全打破了Angular约定(Angular Way(TM)) MVC / MVVM编程范例。不是最好的解决方案。

更新:所以我最终意识到我需要一个更长远的解决方案,一个没有违反这么多最佳实践的解决方案。答案实际上来自Angular最基本的元素,没有它,其余部分都不会起作用(你可以认为对于其他组件,但对于这个组件更为正确):指令。更具体地说:

app.directive('input', ['$parse', function ($parse) {
    return {
        restrict: 'E',
        require: '?ngModel',
        link: function (scope, element, attrs) {
            if(attrs.value) {
                $parse(attrs.ngModel).assign(attrs.value, scope);
            }
        }
    };
}]);

这有许多优点。首先,它不会破坏有助于强化MVC / MVVM的Angular约定。其次,它甚至没有触及jqLit​​e / jQuery,也没有触及底层的DOM函数。第三,它具有保留HTML约定以定义默认值的预期效果,允许(或至少简化)Angular与其他现有技术(如服务器端模板引擎)的使用。

为什么Angular默认不执行此操作?好吧,我不知道实际的答案,没有更多的研究,但一个可能的答案是HTML约定支持静态页面内容,而Angular是为动态页面内容设计的。这意味着在许多地方突破HTML约定,不要让它限制Angular应用程序的可能性。由于控制器应该承担初始化模型的责任(并且在大多数情况下这样的期望是正确的),Angular团队将有动机忽略value属性的内容(及其中的类似物)表格标签)。

当然,使用此方法,对于在初始化控制器之前已存在的任何适用元素,控制器init 可以覆盖value属性。但是,这种行为在整个应用程序中并不一致,因为新元素将触发指令评估,但控制器初始化阶段。 (具有自己的控制器的部分也支持这种行为 - 部分控制器init之前的元素可以被所述init覆盖,但是之后添加的其他元素将不会重新触发init。)

还有许多其他方法可以编写这样的指令,并且它可以扩展为执行任何其他操作,但希望这种方法可以帮助其他人。