J'ai créé une directive qui génère des boutons Twitter. Étant donné que les variables de portée de ces boutons peuvent changer, je dois reconstruire le bouton quand cela se produit. Actuellement, j'utilise jQuery pour empty()
l'élément lié et pour reconstruire le bouton.
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()
Existe-t-il un moyen de faire en sorte que la directive refasse complètement le modèle?
Voici une directive réutilisable que vous pouvez utiliser pour reconstruire le contenu inclus chaque fois qu'un événement est envoyé:
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);
}
};
});
Voici un jsFiddle montrant comment cela fonctionne: http://jsfiddle.net/robianmcd/ZQeU5/
Remarquez comment le contenu de la zone de saisie est réinitialisé chaque fois que vous cliquez sur le bouton "Déclencher le lien". En effet, la zone de saisie est en cours de suppression et ajoutée au DOM chaque fois que l'événement est déclenché.
Vous pouvez utiliser cette directive telle quelle ou la modifier de sorte qu'elle soit déclenchée par scope.$watch()
au lieu d'un événement.
Quelques conseils:
Utilisez le modèle de directive et liez les variables à la portée plutôt que de créer HTML manuellement. Dans ce cas, vous n'avez pas besoin de re-rendre le modèle. Angular le mettra à jour lui-même lorsque les propriétés de la portée changeront.
Utilisez attrs. $ Observe function pour exécuter du code sur le changement de valeur d'attribut
Pour ce faire, vous pouvez également utiliser ng-if.
Par exemple: <myDirective ng-if="renderdirective"></myDirective>
La directive ne sera pas créée tant que votre renderdirective
n'est pas vraie. Cela fonctionnera également dans l'autre sens si vous souhaitez supprimer la directive et la laisser être recréée à l'aide des nouvelles valeurs d'attribut.
Ce que vous essayez de faire correspond à la fonction de compilation dans les directives, il restitue le code HTML. Avez-vous essayé ça?
C'est en quelque sorte une façon hacky de le faire, mais en insérant une variable de vérité ng-if dans la directive, et lorsque vous voulez afficher, définissez ou non la variable de vérité:
angularjs: forcer le rendu/rafraîchir un modèle de directive
Petite variation sur la réponse @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;
}
Utilisez ceci avec:
<div re-render="responsive">
<header-component/>
</div>
et combinez-le avec une diffusion $ quelque part dans votre code:
this.$rootScope.$broadcast( 'responsive' );
Ce que j’ai fait, c’est écouter le redimensionnement de la page, ce qui déclenchera ensuite la diffusion . Je peux ensuite changer le modèle d’un composant de bureau à mobile. Dans la mesure où le header-component
dans l'exemple est inclus, il est rendu et recompilé.
Cela fonctionne comme un charme pour moi.
Merci Rob de m'avoir mis sur la bonne voie.