2

我正在尝试将video.js库连接到我的应用程序中。在应用程序的某一部分,用户可以上传可能包含视频的文件,因此在输出时,我使用ng-repeat循环浏览视频上传,并输出HTML5视频标签。我现在想将指令附加到视频标签,以便video.js可以与它一起使用。

我的视频输出定义为

<video ng-src="{{video.url}}" ng-repeat="video in post.attachments.video" type="{{video.mimetype}}" controls preload="metadata" id="video_{{video.id}}" video>

对于我的video指令,我基本上只是想运行videojs函数来设置它,所以我想调用

videojs(attrs.id, {
    controls: true,
    preload: "metadata",
    techOrder: ["flash"]
  }, function() {});

这被调用了,但我遇到的问题是,ng-repeat当调用这个指令时,还没有完成所有事情,所以attrs.id仍然video_{{video.id}}不是video_23我想要的东西。

在我的视频指令运行之前,我怎样才能等到ng-repeat它完成它的事情,以便我知道我可以使用 ID 属性?

我目前正在使用 Angular 1.1.4。

现在,我的指令有

app.directive("video", function($parse) {
  "use strict";
  return {
    restrict: "A",
    link: function(scope, elm, attrs) {

      videojs(attrs.id, {
        controls: true,
        preload: "metadata",
        techOrder: ["flash"]
      }, function() {});
    }
  };
});
4

3 回答 3

1

问题是在您尝试访问插值时尚未执行字符串插值。您可以使用attrs.$observe(...)它来完成此操作。这是AngularJS 文档的链接(或在下面阅读)。

...
link: function(scope, element, attrs) {
  attrs.$observe('id', function() {
    videojs(attrs.id, {
      controls: true,
      preload: "metadata",
      techOrder: ["flash"]
    }, function() {});
  });
}
...

我还创建了一个显示这种行为的plunker 。

编辑:更新为正确答案。

编辑 2:来自 Angular 文档:

用于$observe观察包含插值的属性的值变化(例如src="{{bar}}")。这不仅非常有效,而且也是轻松获得实际值的唯一方法,因为在链接阶段尚未评估插值,因此此时该值设置为未定义。

于 2013-06-30T01:04:07.923 回答
1

终于有办法了。这不是最好的(由于角度缺乏回调),但它正在工作。我的最终指令是

app.directive("video", function($timeout) {
  "use strict";
  return {
    restrict: "A",
    compile: function(cElm, cAttrs) {
      return function postLink(scope, elm, attrs) {
        // We have to wait until it's actually rendered. Stupid angular with no callback!
        $timeout(function() {
          videojs(scope.$eval(attrs.video), {
            controls: true,
            preload: "metadata",
            techOrder: ["flash"]
          }, function() {});
        })
      }
    }
  };
});

我还必须将我的 html 的定义更改为

<video ng-src="{{video.url}}" ng-repeat="video in post.attachments.video" type="{{video.mimetype}}" controls preload="metadata" id="video_{{video.id}}" video="'video_' + video.id">

注意在video属性中添加了表达式,因为属性中使用的表达式id不能在eval.

我还不得不利用恼人的$timeouthack,因为尝试在元素 ID 上初始化 video.js 不起作用,因为 angular 还没有完成渲染元素,所以当 video.js 试图找到具有该 ID 的元素时DOM,它不匹配任何东西。$timeout尽管我并不太热衷于它,但使用修复了它。

如果有人对此有更好的解决方案,那么我会全神贯注:)

于 2013-06-30T02:36:55.147 回答
0

您可以指定一个priority指令。来自文档AngularJS:指令

优先级 - 当在单个 DOM 元素上定义了多个指令时,有时需要指定应用指令的顺序。优先级用于在调用编译函数之前对指令进行排序。优先级被定义为一个数字。首先编译具有更高数值优先级的指令。具有相同优先级的指令的顺序未定义。默认优先级为 0。

编辑:实际上,这看起来与这个问题非常相似:如何在自定义指令中获取评估的属性

于 2013-06-29T23:18:26.277 回答