我创建了一个生成Twitter按钮的指令。由于这些按钮上的范围变量可能会发生变化,因此我需要在按钮发生时重建它。目前,我正在使用jQuery来empty()
链接元素并重建按钮。
app.directive 'twitterShare', ($timeout, $window) ->
restrict: 'E'
template: '<a href="https://twitter.com/share" class="twitter-share-button" data-text="{{ text }}" data-url="{{ url }}">Twitter</a>'
scope:
text: '@'
url: '@'
link: (scope, el, attrs) ->
scope.$watch 'text', -> rebuild()
scope.$watch 'url' , -> rebuild()
rebuild = ->
$(".twitter-share-button").remove()
tweet = $ '<a>'
.attr 'href', 'https://twitter.com/share'
.attr 'id', 'tweet'
.attr 'class', 'twitter-share-button'
.attr 'data-lang', 'en'
.attr 'data-count', 'none'
.text 'Tweet'
el.prepend tweet
tweet.attr 'data-text', scope.text
tweet.attr 'data-url', scope.url
$window.twttr.widgets.load()
有没有办法让指令完全重新渲染模板?
答案 0 :(得分:46)
以下是您可以使用的可重复使用的指令,它将在发送事件时重建已转换的内容:
app.directive('relinkEvent', function($rootScope) {
return {
transclude: 'element',
restrict: 'A',
link: function(scope, element, attr, ctrl, transclude) {
var previousContent = null;
var triggerRelink = function() {
if (previousContent) {
previousContent.remove();
previousContent = null;
}
transclude(function (clone) {
element.parent().append(clone);
previousContent = clone;
});
};
triggerRelink();
$rootScope.$on(attr.relinkEvent, triggerRelink);
}
};
});
这是一个jsFiddle演示它是如何工作的:http://jsfiddle.net/robianmcd/ZQeU5/
注意每次单击“触发器重新链接”按钮时,输入框的内容如何重置。这是因为每当触发事件时,都会删除输入框并将其添加到DOM。
您可以按原样使用此指令或对其进行修改,使其由scope.$watch()
而非事件触发。
答案 1 :(得分:5)
一些建议:
使用指令模板并将变量绑定到范围,而不是手动创建HTML。在这种情况下,您无需重新渲染模板。当范围属性发生变化时,Angular会自行更新它。
使用attrs.$observe函数在属性值更改
答案 2 :(得分:1)
你尝试做什么跟随指令中的编译功能,它重新呈现html。你试过吗?
这是一种hacky方式,但在指令上放置一个ng-if truthy变量,当你想渲染,设置和取消设置truthy变量时:
angularjs: force re-rendering/ full refresh a directive template
答案 3 :(得分:1)
实现这一目标的另一种方法是使用ng-if。
例如:
<myDirective ng-if="renderdirective"></myDirective>
在renderdirective
不成立之前,不会创建该指令。如果您希望删除该指令并使用新的属性值重新创建它,那么这也将反过来。
答案 4 :(得分:0)
@rob回答的小变化:
import * as angular from 'angular';
class ReRenderDirective implements angular.IDirective {
public restrict = 'A';
public replace = false;
public transclude = true;
constructor( private $rootScope: angular.IRootScopeService, private $compile: angular.ICompileService ) {
}
public link = (
scope: angular.IScope,
element: angular.IAugmentedJQuery,
attr: any,
modelCtrl: any,
transclude: angular.ITranscludeFunction ) => {
let previousContent = null;
let triggerRelink = () => {
if ( previousContent ) {
previousContent.remove();
previousContent = null;
}
transclude(( clone ) => {
element.append( clone );
previousContent = clone;
element.html( attr.compile );
this.$compile( element.contents() )( scope );
} );
};
triggerRelink();
this.$rootScope.$on( attr.reRender, triggerRelink );
}
}
export function reRenderFactory(): angular.IDirectiveFactory {
var directive = ( $rootScope: angular.IRootScopeService, $compile: angular.ICompileService ) => new ReRenderDirective( $rootScope, $compile );
directive.$inject = [ '$rootScope', '$compile' ];
return directive;
}
将此用于:
<div re-render="responsive">
<header-component/>
</div>
并将其与代码中某处的$ broadcast结合使用:
this.$rootScope.$broadcast( 'responsive' );
我做了什么,是听页面大小调整,然后触发广播。
基于此,我能够将组件的模板从桌面更改为移动。因为示例中的header-component
被转换,所以会重新渲染并重新编译。
这对我来说就像是一种魅力。
感谢Rob让我走上正轨。
答案 5 :(得分:-1)
使用ng-bind =&#34;值&#34;而不是{{value}}为我刷新了我的指令模板缓存。
<myDirective><span ng-bind="searchResults.leads.results.length"></span></myDirective>
而不是
<myDirective><span>{{searchResults.leads.results.length}}</span></myDirective>