webentwicklung-frage-antwort-db.com.de

Können Sie templateUrl im laufenden Betrieb ändern?

Ist es möglich, templateUrl im laufenden Betrieb zu ändern, indem Werte im Gültigkeitsbereich der Direktive übergeben werden? Ich möchte Daten an den Controller übergeben, die die Seite basierend auf den von der Direktive übergebenen Daten darstellen 

vielleicht sieht das so aus: 

<div> 
   <boom data="{{myData}}" />
</div> 

.directive('boom', function {
        return {
            restrict: 'E',
            transclude: true,
            scope: 'isolate',
            locals: { data: 'bind' },
            templateUrl: "myTemplate({{boom}}})" // <- that of course won't work.
        }
    });
26
iLemming

Es ist möglich, aber wenn Ihre Vorlage zum Laden von einigen Bereichsdaten abhängt, können Sie die templateUrl -Eigenschaft der Direktive nicht mehr verwenden, und Sie müssen die untergeordnete API verwenden, nämlich $http und $compile.

Etwas, was Sie tun müssen (nur in der Verknüpfungsfunktion möglich), besteht darin, den Inhalt der Vorlage mithilfe von $http abzurufen (vergessen Sie nicht, $templateCache zu verwenden!) Und dann den Inhalt der Vorlage "manuell" zu kompilieren.

Das hört sich vielleicht nach viel Arbeit an, ist aber in der Praxis eher unkompliziert. Ich würde vorschlagen, einen Blick auf die ngInclude Direktive sources zu werfen, wo dieses Muster verwendet wird. 

Hier ist ein Skelett einer solchen Direktive:

app.directive('boom', function($http, $templateCache, $compile, $parse) {
        return {
            restrict: 'E',
            link: function(scope , iElement, iAttrs) {                            
              var boom = $parse(iAttrs.data)(scope);
              $http.get('myTemplate'+boom, {cache: $templateCache}).success(function(tplContent){
                iElement.replaceWith($compile(tplContent)(scope));                
              });              
            } 
        }
    });

vorausgesetzt, es würde als <boom data='name'></boom> verwendet werden. Plunk hier arbeiten: http://plnkr.co/edit/TunwvhPPS6MdiJxpNBg8?p=preview

Bitte beachten Sie, dass ich die Attributauswertung von {{name}} in das Attribut Parsing geändert habe, da eine Vorlage wahrscheinlich nur einmal am Anfang bestimmt werden sollte.

53

Dies ist eine neue Funktion in Angular Versionen 1.1.4+. Ich habe gerade herausgefunden, dass ich bei Verwendung der aktuellen Unstable (1.1.5) eine Funktion in die Vorlagen-URL einer Direktive übergeben kann. Der zweite Parameter der Funktion ist der Wert der Attributdirektive (siehe unten).

Hier ist ein Link zu unveröffentlichte Dokumente , der die offizielle Änderung anzeigt.

Um partials/template1.html als Vorlagen-URL von zu verwenden 

Html:

<div sub_view="template1"></div>

Richtlinie:

.directive('subView', [()->
  restrict: 'A'
  # this requires at least angular 1.1.4 (currently unstable)
  templateUrl: (notsurewhatthisis, attr)->
    "partials/#{attr.subView}.html"
])
16
EpiphanyMachine

Ich habe die Antwort von pkozlowski.opensource etwas geändert.

Von:

var boom = $parse(iAttrs.data)(scope);

Zu:

var boom = scope.data.myData

Das hat für mich funktioniert und kann verwendet werden

<boom data="{{myData}}" /> 

in der Richtlinie.

2
user1947850

Ich hatte ein ähnliches Problem

 return {
        restrict: 'AE',
        templateUrl: function(Elm,attrs){return (attrs.scrolled='scrolled' ?'parts/scrolledNav.php':'parts/nav.php')},
        replace: true,

partnersSite.directive('navMenu', function () {
    return {
        restrict: 'AE',
        templateUrl: function(Elm,attrs){return (attrs.scrolled='scrolled' ?'parts/scrolledNav.php':'parts/nav.php')},
        replace: true,
        link: function (scope, Elm, attrs) {
            scope.hidden = true;
            //other logics
        }
    };
});
<nav-menu scrolled="scrolled"></nav-menu>

2
Karb

Diese Frage wird mit ng-include wie folgt behoben:

MyApp.directive('boom', function() {
    return {
      restrict: 'E',
      transclude: true,
      scope: 'isolate',
      locals: { data: 'bind' },
      templateUrl: '<div ng-include="templateUrl"></div>',
      link: function (scope) {
        function switchTemplate(temp) {
          if (temp == 'x')
          { scope.templateUrl = 'XTemplate.html' }
          else if (temp == 'y')
          { scope.templateUrl = 'YTemplate.html' }
        }
      }
    }
});

Rufen Sie die switchTemplate-Funktion mit einem beliebigen Temp-Parameter in der Link-Funktion der Direktive auf.

1
Iman Bahrampour

Dies ist eine Folgeantwort, die einige Probleme mit früheren Antworten anspricht. Insbesondere werden Vorlagen nur einmal kompiliert (was sehr wichtig ist, wenn Sie viele davon auf Ihrer Seite haben) und nach dem Verknüpfen der Vorlage nach Änderungen in der Vorlage suchen. Außerdem werden Klasse und Stil vom ursprünglichen Element in das Format kopiert template (wenn auch nicht auf die sehr elegante Art und Weise, die ein Winkel intern macht, wenn Sie "replace: true" verwenden. Im Gegensatz zu der derzeit unterstützten, winkelunterstützten Methode, eine Funktion für template oder templateUrl zu verwenden, können Sie mithilfe von Bereichsinformationen die zu ladende Vorlage bestimmen.

.directive('boom', ['$http', '$templateCache', '$compile', function ($http, $templateCache, $compile) {
    //create a cache of compiled templates so we only compile templates a single time.
    var cache= {};
    return {
        restrict: 'E',
        scope: {
            Template: '&template'
        },
        link: function (scope, element, attrs) {
            //since we are replacing the element, and we may need to do it again, we need
            //to keep a reference to the element that is currently in the DOM
            var currentElement = element;
            var attach = function (template) {
                if (cache[template]) {
                    //use a cloneAttachFn so that the link function will clone the compiled elment instead of reusing it
                    cache[template](scope, function (e) {
                        //copy class and style
                        e.attr('class', element.attr('class'));
                        e.attr('style', element.attr('style'));
                        //replace the element currently in the DOM
                        currentElement.replaceWith(e);
                        //set e as the element currently in the dom
                        currentElement = e;
                    });
                }
                else {
                    $http.get('/pathtotemplates/' + template + '.html', {
                        cache: $templateCache
                    }).success(function (content) {
                        cache[template] = $compile(content);
                        attach(template);
                    }).error(function (err) {
                        //this is something specific to my implementation that could be customized
                        if (template != 'default') {
                            attach('default');
                        }
                        //do some generic hard coded template
                    });
                }
            };

            scope.$watch("Template()", function (v, o) {
                if (v != o) {
                    attach(v);
                }
            });
            scope.$on('$destroy', function(){
                currentElement.remove();
            });
        }
    };
} ])
1
Joe Enzminger

Diese Antworten sind gut, aber nicht professionell. Es gibt eine Syntax für die Verwendung von templateUrl, die wir nicht oft verwenden .Es kann eine Funktion sein, die eine URL zurückgibt. Diese Funktion hat einige Argumente. Wer mehr will, ist hier ein cooler Artikel

http://www.w3docs.com/snippets/angularjs/dynamically-change-template-url-in-angularjs-directives.html

0