ディレクティブのスコープで値を渡すことで、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.
}
});
可能ですが、ロードするテンプレートがスコープデータに依存している場合、ディレクティブの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>
として使用されると仮定します。ここでの作業プランク: http://plnkr.co/edit/TunwvhPPS6MdiJxpNBg8?p=preview
おそらくテンプレートは最初に一度だけ決定されるべきなので、属性評価を{{name}}
から属性解析に変更したことに注意してください。
これはAngularバージョン1.1.4+の新機能です。現在の不安定版(1.1.5)を使用すると、ディレクティブのテンプレートURLに関数を渡すことができることがわかりました。関数の2番目のパラメーターは、以下に示すように属性ディレクティブの値です。
未公開ドキュメント へのリンクは公式な変更を示しています。
partials/template1.html
をテンプレートURLとして使用するには
HTML:
<div sub_view="template1"></div>
指令:
.directive('subView', [()->
restrict: 'A'
# this requires at least angular 1.1.4 (currently unstable)
templateUrl: (notsurewhatthisis, attr)->
"partials/#{attr.subView}.html"
])
Pkozlowski.opensourceからの回答を少し変更しました。
から:
var boom = $parse(iAttrs.data)(scope);
に:
var boom = scope.data.myData
それは私のために働いた、それは使用することが可能です
<boom data="{{myData}}" />
ディレクティブで。
同様の問題がありました
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>
この問題は、次のようにng-includeで修正されます。
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' }
}
}
}
});
ディレクティブのリンク関数で任意のtempパラメーターを指定してswitchTemplate関数を呼び出します。
これは、以前の回答に関するいくつかの問題に対処するフォローアップ回答です。特に、テンプレートを一度だけコンパイルします(ページ上にこれらがたくさんある場合は重要です。リンクされた後、テンプレートへの変更を監視します。また、元の要素からクラスとスタイルをテンプレート(「replace:true」を使用すると、angularは内部的に非常にエレガントな方法ではありません。テンプレートまたはtemplateUrlの関数を使用する現在のangularサポート方法とは異なり、スコープ情報を使用してロードするテンプレートを決定します。
.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();
});
}
};
} ])
これらの答えは良いですが、専門的ではありません。よく使用しないtemplateUrl
を使用する構文があります。urlを返す関数でもかまいません。関数にはいくつかの引数があります。ここにもっと欲しいなら、クールな記事があります