2014-12-24 4 views
4

Я пытаюсь создать директиву, которая будет загружать страницу и сделать ее доступной в сервисе и как область видимости, и она будет содержать контент внутри элемента директивы.AngularJS как создать директиву с содержимым HTML?

Это должно быть довольно самоуправления объяснения (упрощенно), что я пытаюсь сделать:

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

Не могли бы вы сделать что-то вроде этого?

ответ

1

Ваша проблема возникает из сферы, в которой ваш контент включены через границы. Может показаться, что html в вашем теге <cms-page> наследует изолированную область действия в директиве 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

Если требуется переменная шаблона, вы можете выбрать один динамически с помощью функции шаблона:

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 контента и указать его в зависимости от того, какой вы хотите. Функция 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); 
    }); 
} 
1

Как уже упоминалось в AngularJS $compile documentation, regarding transclusion: включение

является процесс извлечения коллекции DOM элемента из одной части DOM и копирования их другая часть DOM, при сохранении их подключения к исходному пространству AngularJS откуда они были t aken.

Это говорит о том, что передаваемый элемент имеет доступ только к области, из которой он был взят. Если вы хотите иметь pageData, тогда вам нужно будет указать определение области вашей директивы, чтобы обеспечить двустороннюю привязку данных к pageData.

DEMO

.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); 
       }); 
      } 
     }; 
    }]); 
Смежные вопросы