当使用服务器端模板和客户端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模型在客户端上绑定该值一次?
答案 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(或嵌入式jqLite子集,如果没有完整的jQuery)的基础上解决这个问题而不移动内容,甚至触及ng-在里面。具体来说,您可以在控制器初始化阶段使用(Angular/jqLite version)standard 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>
标记,而jqLite不支持选择器,因此找到所需的确切元素可能有点棘手。我只想在那时包含完整的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约定。其次,它甚至没有触及jqLite / jQuery,也没有触及底层的DOM函数。第三,它具有保留HTML约定以定义默认值的预期效果,允许(或至少简化)Angular与其他现有技术(如服务器端模板引擎)的使用。
为什么Angular默认不执行此操作?好吧,我不知道实际的答案,没有更多的研究,但一个可能的答案是HTML约定支持静态页面内容,而Angular是为动态页面内容设计的。这意味着在许多地方突破HTML约定,不要让它限制Angular应用程序的可能性。由于控制器应该承担初始化模型的责任(并且在大多数情况下这样的期望是正确的),Angular团队将有动机忽略value
属性的内容(及其中的类似物)表格标签)。
当然,使用此方法,对于在初始化控制器之前已存在的任何适用元素,控制器init 可以覆盖value
属性。但是,这种行为在整个应用程序中并不一致,因为新元素将触发指令评估,但不控制器初始化阶段。 (具有自己的控制器的部分也支持这种行为 - 部分控制器init之前的元素可以被所述init覆盖,但是之后添加的其他元素将不会重新触发init。)
还有许多其他方法可以编写这样的指令,并且它可以扩展为执行任何其他操作,但希望这种方法可以帮助其他人。