2013-01-31 8 views
26

ディレクティブのスコープに値を渡して、その場でtemplateUrlを変更することはできますか? は、私はそのように見えますその場でtemplateUrlを変更できますか?

何か多分ディレクティブから渡されたデータに基づいてページをレンダリングするコントローラにデータを渡したい:

<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. 
     } 
    }); 

答えて

53

ことは可能ですが、あなたのテンプレートがされるようにする場合ロードされたデータはスコープのデータによって異なります。ディレクティブのtemplateUrlプロパティを使用できなくなり、下位レベルのAPI、つまり$http$compileを使用することが義務付けられます。

おおよそ(リンク機能でのみ可能な)$http$templateCacheを含むことを忘れないでください)を使用してテンプレートのコンテンツを取得してから、テンプレートのコンテンツを「手動で」コンパイルしてください。

多くの作業があるように聞こえるかもしれませんが、実際にはむしろ簡単です。私はngIncludeディレクティブsourcesを見てみることをお勧めします。ここ

は、このような指令の骨格である:

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));     
       });    
      } 
     } 
    }); 

は、<boom data='name'></boom>として使用されると仮定します。ファンクション評価は{{name}}から属性解析に変更されていることに注意してください。おそらくテンプレートは最初に一度だけ決定されるべきであるからです。

+0

ええ、私はngIncludeで再生しようとしますが、私よできないローカル変数の値を取得する方法を示します。私の場合に 'データ 'を得る方法は?私はattrs.dataを試していますが、 'undefined'を返します。 – Agzam

+0

詳細情報があります。テンプレートが$ダイジェストサイクルの一部として動的に変更される可能性があるので、実際に属性の補間を使用するかどうかはわかりません。しかし、本当にしたい場合は、属性を観察する必要があります。 –

+0

私の問題も解決しました。ありがとう! – OpherV

16

これは、Angularバージョン1.1.4+の新機能です。現在の不安定な(1.1.5)を使用すると、関数を指示のテンプレートURLに渡すことができます。関数の2番目のパラメーターは、以下に示すような属性指示の値です。

ここには、公式の変更を示すunpublished docsへのリンクがあります。

HTMLからのテンプレートURLとしてpartials/template1.htmlを使用するには:私は少しpkozlowski.opensourceからの回答を変更した

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

パラメータは '(要素、属性)' – EpiphanyMachine

+0

ありがとうございました –

2

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

指令。

から:

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

へ:私のために働いたし、それがディレクティブで

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

を使用することが可能です

var boom = scope.data.myData 

+0

上記のPlnkrからフォークされた例:[http://plnkr.co/edit/7BQxFEZ12Zxw9J9yT7hn](http://plnkr.co/edit/7BQxFEZ12Zxw9J9yT7hn? p =プレビュー)。 'iAttrs.data'に値(' iAttrs'オブジェクトを記録したときに見える)があっても、この方法はAngular 1.0.8では機能しません。それにアクセスしようとする。 – GFoley83

1

これは、以前の回答のいくつかの問題に対処するフォローアップの回答です。特に、テンプレートを一度コンパイルするだけです(これはページ上にたくさんある場合は重要です。リンクされた後のテンプレートの変更を監視します)、元の要素からクラステンプレートを使用する際には、現在の角度でサポートされている方法とは異なり、スコープ情報を使用して読み込むテンプレートを決定することができます。

.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(); 
      }); 
     } 
    }; 
} ]) 
0

これらの答えは良いですが、プロではない。私たちは頻繁に使用していないtemplateUrlを、使用する構文があります。これは、URL .That機能はいくつかの引数を持って返す関数とすることができる。あなたの場合ここにもっと欲しいクールな記事

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

+0

それは心に問題ではありません。実際にOPのようなデモアプリケーションを作成した場合、補間された値をディレクティブの 'templateURL'関数に渡すだけでは不十分です。 –

2

私が持っていた同様の問題

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>

+0

これは、の実行に役立ちます。つまり、属性値が実行時に変更され、それに基づいて異なるテンプレートURLを設定する必要があります。 –

関連する問題