Как перерисовать шаблон в директиве AngularJS?
Я создаю директиву, которая генерирует кнопки Twitter. Поскольку переменные области действия на этих кнопках могут измениться, мне нужно перестроить кнопку, когда это произойдет. В настоящее время я использую jQuery для empty()
связанного элемента и перестраиваю кнопку.
app.directive 'twitterShare', ($timeout, $window) ->
restrict: 'E'
template: '<a href="#" onclick="location.href='https://twitter.com/share'; return false;" 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()
Есть ли способ заставить директиву полностью повторно отобразить шаблон?
Ответы
Ответ 1
Вот директива многократного использования, которую вы можете использовать, которая будет перестраивать транслируемый контент всякий раз, когда отправляется событие:
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/
Обратите внимание, что содержимое поля ввода получает reset каждый раз, когда вы нажимаете кнопку "Trigger Relink". Это связано с тем, что окно ввода удаляется и добавляется в DOM при каждом запуске события.
Вы можете использовать эту директиву как есть или изменить ее так, чтобы она срабатывала scope.$watch()
вместо события.
Ответ 2
Несколько советов:
-
Использовать шаблон директивы и связывать переменные с областью, а не создавать HTML вручную. В этом случае вам не нужно повторно отображать шаблон. Angular будет обновлять его сам, когда изменяются свойства области.
-
Использовать функцию attrs. $наблюдать для запуска некоторого кода при изменении значения атрибута
Ответ 3
То, что вы пытаетесь сделать, соответствует функции компиляции в директивах, она повторно отображает html. Вы пробовали это?
Это своего рода хакерский способ сделать это, но в директиве вставлять в директиву правнущую переменную ng-if, а когда вы хотите рендерить, установить и отключить истинную переменную:
angularjs: принудительное повторное рендеринг/полное обновление шаблона директивы
Ответ 4
Другой способ добиться этого - использовать ng-if.
Например:
<myDirective ng-if="renderdirective"></myDirective>
Директива не будет создана до тех пор, пока ваш renderdirective
не будет прав. Это также будет работать наоборот, если вы хотите удалить эту директиву и позволить ей воссоздаваться с использованием новых значений атрибутов.
Ответ 5
Небольшое отклонение от ответа @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
в этом примере завершается, он получает перезапись и перекомпилируется.
Это работает как прелесть для меня.
Спасибо Робу за то, что он меня на правильном пути.
Ответ 6
Использование ng-bind = "value" вместо {{value}} обновило мой кеш шаблона директивы для меня.
<myDirective><span ng-bind="searchResults.leads.results.length"></span></myDirective>
вместо
<myDirective><span>{{searchResults.leads.results.length}}</span></myDirective>