在 JavaScript 中初始化 Angular 指令

Initializing an Angular Directive in JavaScript

我的模板中有一个指令。效果很好:

<ul class="activity-stream">
    <my-activity-stream-item ng-repeat="activity in vm.activities" activity="activity"></my-activity-stream-item>
</ul>

我基本上想在该模板中包含与传单地图中的弹出窗口相同的 HTML,但我不知道如何在代码中创建它。这是我尝试过的:

for (i = 0; i < activities.length; i++) {
  var activity = activities[i];
  var marker = L.marker([activity.location.lat, activity.location.lng]);
  marker.type = activity.type;
  marker.bindPopup( '<my-activity-stream-item activity="activity"></my-activity-stream-item>' );
  marker.addTo( map );
}

我真的没想到它会起作用,我觉得我必须以某种方式通过范围...但我完全不知道该怎么做。

var app = angular.module('myPortal');

app.factory('TemplateService', TemplateService);
app.directive('myActivityStreamItem', myActivityStreamItem);

function myActivityStreamItem( $compile, TemplateService ) {
  return {
      restrict: 'E',
      link: linker,
      transclude: true,
      scope: {
          activity: '='
      }
  };

  function linker(scope, element, attrs) {
    scope.rootDirectory = 'images/';

    TemplateService.getTemplate( 'activity-' + scope.activity.type ).then(function(response) {
      element.html( response.data );
      $compile(element.contents())(scope);
    });
  }
}

function TemplateService( $http ) {
  return {
    getTemplate: getTemplate
  };

  function getTemplate( templateName ) {
    return $http.get('/templates/' + templateName + '.html');
  }
}

(注意 - 我只使用 Angular 大约一个星期,所以如果您认为我做错了,请告诉我)

编辑: 我采纳了 Chandermani 的建议并将指令切换为 ngInclude

<ul class="activity-stream">
    <li ng-repeat="activity in vm.activities" ng-include="'/templates/activity-' + activity.type + '.html'"></li>
</ul>

这太棒了!我还尝试使用 Josh 的建议来编译 JavaScript 中的 HTML,但是我还没有完成...

var link = $compile('<li ng-include="\'/templates/activity-' + activity.type + '.html\'"></li>');
var newScope = $rootScope.$new();
newScope.activity = activity;
var html = link( newScope );
marker.bindPopup( html[0] );

这会导致出现弹出窗口,但弹出窗口中包含的 HTML 是一条评论:<!-- ngInclude: '/templates/activity-incident.html' -->

我是否必须以某种方式将它传递给 li 中的 activity?

编辑 2: 知道了!如 Issue #4505 中所述,您需要将代码段包裹在某些东西中,所以我将 ngInclude 包裹在 div:

var link = $compile( '<div><ng-include src="\'/templates/activity-incident.html\'"></ng-include></div>' );

不确定我是否理解你的问题,但你可以做的是使用 ng-include 指令,它可以使用模板表达式来动态加载模板。类似于:

<ul class="activity-stream">
    <li ng-repeat="activity in vm.activities" ng-include="'/templates/activity-' + activity.type + '.html'"></li>
</ul>

您可能不需要此处的指令。

任何时候你想添加原始 HTML 到页面并让 Angular 处理它,你需要使用 $compile 服务。

在模板上调用 $compile 将 return 一个链接函数,然后可用于将范围对象绑定到。

var link = $compile('<span>{{someObj}}</span>');

将该函数链接到 scope 对象将生成一个元素,然后可以将其附加到 DOM。

//Or the scope provided by a directive, etc...
var newScope = $rootScope.$new();

var elem = link(newScope);

//Could also be the element provided by directive
$('someSelector').append(elem);

这是您需要能够告诉 Angular 处理您的 DOM 元素的基本流程。通常这是通过指令完成的,在这种情况下这可能也是您需要的。