我有一个简单的角控制器在我的应用程序。我希望增强包含静态内容的页面,与角。这将允许我有一个很好的,内容丰富的页面,为那些没有JS的人(谁?!)和网络爬虫和读者。
到目前为止,我已经确定了一些方法来做到这一点,可能使用自定义指令,或者通过在'ng-bind-template'指令中增加内容(这显然不是理想的)。
我对angular的世界还很陌生,所以我想尝试并获得这个场景的最佳实践。
最好的方法是什么?
控制器:
app.controller('TestArticle',function($scope, feed){
$scope.initValue = "This is angular injecting this"
$scope.activate = function(){
$scope.eTitle = "Dynamic title";
$scope.eContent = "Dynamic content";
};
});
标记:
(这里的问题是"静态内容"被"如果angular初始化"所取代)
<div ng-controller="TestArticle">
<div ng-cloak ng-bind-template='{{eTitle}}'>Static content</div>
<div ng-cloak ng-bind-template='{{eContent}}'>Some more content</div>
<div ng-cloak>{{initValue}}</div>
<a href ng-click="activate()" ng-cloak>click to activate</a>
</div>
编辑
我应该清楚,即使angular是自引导的,其目的是保持默认内容完整,而不是用动态内容代替它。这只希望在激活按钮被点击后才能实现。我试过下面的方法,但它涉及到双倍的内容,如果它是一篇完整的文章,可能会变得笨重。
<div ng-controller="TestArticle">
<div ng-cloak ng-bind-template='{{eTitle || "Static Content"}}'>Static content</div>
<div ng-cloak ng-bind-template='{{eContent || "Some more content"}}'>Some more content</div>
<div ng-cloak>{{initValue}}</div> <a href ng-click="activate()" ng-cloak>click to activate</a>
</div>
你可以创建一个简单的指令来创建你想要的html结构。
我建议这是你的新html:
<div ng-cloak sk-custom-bind="eTitle">Static content</div>
请注意,您不必使用静态内容指定or子句。
现在你可以创建一个指令来为你构建html模板:
app.directive('skCustomBind',function() {
return {
restrict: 'A',
template: function(elem, attrs) {
var templ = "<div ";
templ += "ng-bind-template='{{";
templ += attrs.skCustomBind;
templ += ' || "';
templ += elem.text();
templ += '"';
templ += "}}'></div>";
return templ;
},
replace: true
};
});
就这么简单,你就拥有了你想要的功能,而不需要重复。
这里的问题是,当你定义控制器时,angular会解析整个html,找到所有的变量,并使用$scope将它们与相应的控制器项链接起来。
所以,当angular初始化时,由于eTitle和eContent没有任何值(因为你只在函数中初始化它们),它在点击最后一项时被调用(在你的应用程序中运行良好)。
因此,在单击按钮之前,静态文本将被$scope替换。eTitle和$scope。内容,两者都是未定义的。因此标签内没有文本。
所以解,1. 要么你用静态文本初始化控制器内的变量,就像你在"This is angular inject This"(这是唯一的原因!)中所做的那样:
应用程序。控制器(TestArticle,函数(范围、提要){
$scope.initValue = "This is angular injecting this";
$scope.eTitle = "Dynamic title";
$scope.eContent = "Dynamic content";
$scope.activate = function(){
$scope.eTitle = "Dynamic title";
$scope.eContent = "Dynamic content";
};
});
或者你可以使用ng-init初始化html中的变量,它只会初始化html中的变量:
<div ng-controller="TestArticle">
<div ng-init="eTitle = 'Static Content'" ng-cloak ng-bind-template='{{eTitle}}'>Static content</div>
<div ng-init="eContent = 'Some more content'" ng-cloak ng-bind-template='{{eContent}}'>Some more content</div>
<div ng-cloak>{{initValue}}</div>
<a href ng-click="activate()" ng-cloak>click to activate</a>
</div>
问题是,当你开始使用angular时,html会被劫持,angular会开始使用自己的变量
感谢@JoseM让我走上正轨,并帮助我找到以下解决方案…
<<p> 解决方案/strong> 我的标记:注意:自定义指令和属性('cg-dyn'和'cg-content')。当angular启动时,这些不会初始化任何值。再往下看,你会看到它们是如何从控制器作用域通过一个隔离作用域进行映射的。
<div ng-controller="TestArticle">
<div ng-cloak cg-dyn cg-content="eTitle">Static content</div>
<div ng-cloak cg-dyn cg-content="eContent">Some more content</div>
<div ng-cloak>{{initValue}}</div>
<a href ng-click="upDateTitle()" ng-cloak>Update title</a> | <a href ng-click="upDateContent()" ng-cloak>Update content</a>
</div>
我的控制器:
app.controller('TestArticle',function($scope, feed){
$scope.initValue = "This is angular injecting this"
$scope.upDateTitle = function(){
$scope.eTitle = "Dynamic title";
};
$scope.upDateContent = function(){
$scope.eContent = "Dynamic Content Lorem ipsum";
};
});
最后是My Directive
app.directive('cgDyn',function() {
return {
restrict: 'A',
scope:{
'content':'=cgContent'
// this is a two way binding to the property defined in 'cg-content
},
link: function(scope, elem, attrs) {
// below is a watcher keyed on a combination content
scope.$watch('content',function(){
if(scope.content){
elem.html(scope.content);
// and here is the bit, normally plumbed by default, but instead we only replace the html if the value has been set
}
});
},
controller: 'TestArticle',
replace: false
};
});
谢谢大家的帮助。我相信会有更好的解决方案,所以请继续提出建议!