[英]AngularJS how to create a directive that has HTML content?
我正在嘗試創建一個指令,它將加載頁面並使其在服務中可用並作為范圍,並且它將在directives元素中包含內容。
這應該是我嘗試做的非常自我解釋(簡化):
<cms-page page-id="829">
<h1>Testing</h1>
<ul ui-sortable ng-model="pageData.sections.main">
<li ng-repeat="element in pageData.CmsPage.sections.main track by $index">
<div ng-include="'/templates/cms/elements/' + element.element_type + '.html'"></div>
</li>
</ul>
<pre>{{pageData | json}}</pre>
</cms-page>
現在的問題是它沒有顯示{{pageData}}。 如何創建一個指令來顯示現有的標記並解析現有的標記和子指令?
這是我的指示:
angular.module(cms).directive('cmsPage', ['CmsPage', 'CmsPagesService', function(CmsPage, CmsPagesService) {
return {
restrict: 'E',
transclude: true,
template: '<div ng-transclude></div>',
scope: {
pageId: '@pageId'
},
controller: function($scope) {
$scope.pageData = {};
CmsPagesService.get($scope.pageId).then(function(result) {
if (result.status == 'success') {
$scope.pageData = result.data;
} else {
throw 'Page failed to load.';
}
});
$scope.$watch('pageData', function() {
CmsPage.setPage($scope.pageData);
});
}
};
}]);
如AngularJS $ compile文檔中所述,關於transclusion :
Transclusion是從DOM的一個部位提取的DOM元素的集合,將它們復制到DOM的另一部分, 同時保持它們從 他們被帶到這里 原來AngularJS范圍連接的過程。
這表明transcluded元素只能訪問從中獲取的元素。 如果你想讓pageData
可用,那么你必須指示你的指令的范圍定義來提供對pageData
的雙向數據綁定。
.directive('cmsPage', ['CmsPage', 'CmsPagesService', function(CmsPage, CmsPagesService) {
return {
restrict: 'E',
transclude: true,
template: '<div ng-transclude></div>',
scope: {
pageId: '@pageId',
pageData: '='
},
controller: function($scope) {
$scope.pageData = {};
CmsPagesService.get($scope.pageId).then(function(result) {
$scope.pageData = result.data;
});
$scope.$watch('pageData', function() {
CmsPage.setPage($scope.pageData);
});
}
};
}]);
您的問題來自您的已轉換內容的范圍。 看起來好像你的<cms-page>
標簽中的html繼承了cms-page
指令中的隔離范圍 - 假設它嵌套在它內部是一個公平的假設 - 但實際上它並沒有。 默認情況下,被轉換的內容將遵循其獲取的范圍。
這樣做的結果是,在實踐中,你有兩個並行的范圍 - pageData
所在的指令上的隔離范圍,以及管理你的標記的原始范圍,其中pageData
是未定義的(並且這個范圍是你的transcluded html被綁定的至)。 您可以采取兩種方法來糾正這個問題:
指令模板
如上所述,似乎沒有理由在此需要進行翻譯。 這似乎是一個相當規則的指令,指令html可以存在於指令本身:
HTML :
<cms-page page-id="829"></cms-page>
指令 :
template: // the original html to be transcluded
這有一些優點:
pageData
固有地綁定到正確的范圍 pageData
變得混亂 如果需要變量模板,可以使用模板函數動態選擇一個:
HTML :
<cms-page page-id="829" page-template="templateA"></cms-page>
指令 :
template: function(tElem, tAttrs) {
if(tAttrs.pageTemplate) {
return '<div>...</div>';
} // and so on...
}
手動轉換
如果由於某種原因你不能使用指令模板,那么你可以自己轉換內容並將其指向你喜歡的范圍,而不是讓角度轉換你的內容(通過將其與拍攝范圍相關聯)。 transclude函數可用作鏈接函數的第五個參數:
transclude: true,
template: '<div></div>',
scope: {
pageId: '@'
}
link: function(scope, elem, attrs, ctrl, transclude) {
transclude(scope, function(clone) {
// transcluded html is now bound to the isolated scope of the directive
// therein making pageData accessible "externally"
elem.append(clone);
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.