簡體   English   中英

在渲染模板之前解析AngularJS指令中的內容

[英]Parse content within AngularJS directive before rendering template

我在頁面上有一個由服務器呈現的元素。 我們稱之為播放列表 這將是一個指令。
<div playlist></div>

播放列表在Angular編譯時間之前包含許多曲目
<div class="Track" data-track-name="Pompeii" data-*="etc">...</div>

加載頁面后,我將包括AngularJS並解析播放列表和指令。

當我初始化播放列表指令時,我想在編譯它的模板之前循環遍歷它的內容,並使用收集的數據在屬於播放列表指令的ng-repeat指令中繪制軌道指令。

問題:

  1. 在模板替換指令標記內的任何內容之前,是否存在用於解析內容的本機功能? 一旦我進入指令控制器,內容就已經被替換了。

  2. 我的問題有更好的解決方案嗎? 遺憾的是,我不得不使用已在頁面上呈現的內容作為數據源,作為該項目的大量需求的解決方案

  3. 我可以在服務器的內容中使用track指令來避免DOM操作嗎?

額外的解釋

在編譯之前:

<div playlist>
   <div class="Track" data-track-name="Pompeii">Pompeii</div>
   <div class="Track" data-track-name="Weight of living">Weight of living</div>
</div>

編譯后:

<div playlist>
   <!-- from playlist template -->
   <div class="Playlist">
       <div class="Playlist-controls">....</div>
       <div class="Playlist-tracks">
           <div track ng-repeat="track in tracks">
               <!-- from track template -->
               <div class="Track">...</div>
            </div>
       </div>

   </div>
</div>

假設這是您的數據結構,您可以在沒有指令的情況下輕松完成所有操作:

數據結構/控制器

function ctrl($scope) {
$scope.Playlists = [
  { name: 'Playlist 1', tracks: [ 'Track 1', 'Track 2', ..., 'Track n'] },
  { name: 'Playlist 2', tracks: [ 'Track 1', 'Track 2', ..., 'Track n'] },
  ...
  { name: 'Playlist n', tracks: [ 'Track 1', 'Track 2', ..., 'Track n'] }
];
}

模板:

<div ng-controller="ctrl">
  <div ng-repeat="playlist in Playlists">
    <div> {{ playlist.name }} </div>
    <div ng-repeat="track in playlist.tracks">
       {{ track }}
    </div>
  </div>
</div>

[編輯]

由於您需要解析DOM,因此可以使用此指令來執行此操作。 它將解析DOM並將其放入控制器范圍數組中。 然后,您可以將此范圍傳遞到模板或模板URL中。 使用你需要的任何jQuery擦除原始DOM。 的jsfiddle

var myApp = angular.module('myApp',[]);

myApp.directive('playlist', function() {
    return {
        restrict: 'A',
        scope: false,
        link: {
            pre: function(scope, element) {
                $('.Track').each(function(index, ele) {
                   scope.tracks.push($(ele).attr('data-track-name')); 
                });
                console.log(scope.tracks);
            },
            post: function(scope, element) {
              // do any compiling, etc...    
            }
        },
        controller: function($scope, $element) {
            $scope.tracks = [];
        }
    }
});

[編輯#2]包括拜爾的建議。 添加此項以防將來有人發現這有用。 的jsfiddle

模板:

<div ng-app="myApp">
    <script type="text/ng-template" id="tpl.html">
        <div>My playlist controls</div>
        <div ng-repeat="track in tracks">
           {{ track }}
        </div>
   </script>
    <div playlist>
       <div class="Track" data-track-name="Pompeii">Pompeii</div>
       <div class="Track" data-track-name="Weight of living">Weight of living</div>
    </div>
</div>

指示:

var myApp = angular.module('myApp',[]);

myApp.directive('playlist', function($compile, $templateCache) {
    var extractData = function(scope) {
        $('.Track').each(function(index, ele) {
            scope.tracks.push($(ele).attr('data-track-name'));
        });
    }

    return {
        replace: true,
        restrict: 'A',
        compile: function(ele, attr, ctrl) {
            return {
              pre: function preLink(scope, ele, attr, ctrl) {
                  extractData(scope);
              },
              post: function postLink(scope, ele, attr, ctrl) {
                  ele.html($templateCache.get("tpl.html"));
                  $compile(ele.contents())(scope);
              }
            }
        },
        controller: function($scope, $element) {
            $scope.tracks = [];
        }
    }
});

我找到了一個使用ngTransclude非常滿意的解決方案。

我從服務器以指令形式為軌道編寫我的內容:

<div track track-id="245" track-name="Pompeii" track-duration="3.24">Pompeii</div>

在我的播放列表模板中,我使用了一個<div ng-transclude></div>指令,該指令從原始DOM中獲取播放列表的內容,將其解析為單獨的指令並注入到播放列表模板的指定部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM