Angular JS无法在页面/路由更改上呈现社交媒体窗口小部件

Hol*_*lly 5 api ajax angularjs

我正在创建一个Angular App,它对Drupal CMS系统进行ajax调用以获取一些内容.其中一些内容包括来自Facebook,Twitter,Instagram和Youtube的小部件.

ajax调用是用postsController 和完成的postsService.

我无法正确渲染这些社交媒体小部件.当有人直接使用小部件进入页面时,我已经让它们正确呈现,但如果他们改变了路径(页面视图),小部件将无法加载.我相信这是因为API使用的脚本仅在页面加载事件上运行.

起初角度根本没有渲染小部件,但我做了两件事来让它工作.

  1. 我把CDN链接放在头部的API javascript中,用于wach API,例如 /platform.twitter.com/widgets.js
  2. 我使用我命名的自定义指令更改了我从Drupal获取的数据的角度重新编译 compileAjax

当用户更改视图/路径时,我该怎么做才能渲染这些内容?

下面是htmldoc中代码的屏幕截图和示例,其中问题在单个htmldoc中复制.小部件在页面加载时正确呈现,但在单击" 转到页面"链接之一时则不会.

在此输入图像描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>

    <link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.slick/1.6.0/slick.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
    <script src="https://code.angularjs.org/1.5.9/angular-sanitize.min.js"></script>
    <script src="https://code.angularjs.org/1.5.9/angular-route.min.js"></script>
    <script type="text/javascript" src="//cdn.jsdelivr.net/jquery.slick/1.6.0/slick.min.js"></script>

    <script>
        var app = angular.module('app', ['ngSanitize','ngRoute']);

        app.config(function($routeProvider) {
            $routeProvider.when('/page1', {
                controller: 'postsController as postsCtrl',
                templateUrl: 'page1.htm'
            }).when('/page2', {
                controller: 'postsController as postsCtrl',
                templateUrl: 'page2.htm'
            })
            .otherwise({ redirectTo: '/page1' });
        });

        app.controller('postsController', ['postsService',function(postsService) {
            var postsCtrl = this;
            postsCtrl.test = 'this is an expression from the controller'
            var promise = postsService.getPost(1);

            promise.then(function(data) {
                postsCtrl.data = data.data;
                // I can't access the API on SO so am replicating what I would get from it here.
                postsCtrl.twitter = "<div data-oembed-url=\"https:\/\/twitter.com\/NatGeo\/status\/811610711671656448\">\n<div style=\"max-width:320px;margin:auto;\">\n<blockquote align=\"center\" class=\"twitter-tweet\">\n<p dir=\"ltr\" lang=\"en\" xml:lang=\"en\">Polar bears are just one of the animals that will benefit from President Obamas\u00a0recent ban on oil drilling <a href=\"https:\/\/t.co\/MX4ZnX7TNw\">https:\/\/t.co\/MX4ZnX7TNw<\/a><\/p>\n\u2014 National Geographic (@NatGeo) <a href=\"https:\/\/twitter.com\/NatGeo\/status\/811610711671656448\">December 21, 2016<\/a><\/blockquote>\n<script async=\"\" charset=\"utf-8\" src=\"\/\/platform.twitter.com\/widgets.js\"><\/script><\/div>\n<\/div>";
                postsCtrl.facebook = "<div data-oembed-url=\"https:\/\/www.facebook.com\/natgeo\/posts\/10154212815083951\">\n<div id=\"fb-root\">\u00a0<\/div>\n<script>\n<!--\/\/--><![CDATA[\/\/ ><!--\n(function(d, s, id) {\n  var js, fjs = d.getElementsByTagName(s)[0];\n  if (d.getElementById(id)) return;\n  js = d.createElement(s); js.id = id;\n  js.src = \"\/\/connect.facebook.net\/en_US\/sdk.js#xfbml=1&version=v2.3\";\n  fjs.parentNode.insertBefore(js, fjs);\n}(document, 'script', 'facebook-jssdk'));\n\/\/--><!]]>\n<\/script><div class=\"fb-post\" data-href=\"https:\/\/www.facebook.com\/natgeo\/posts\/10154212815083951\" data-width=\"550\">\n<blockquote cite=\"https:\/\/www.facebook.com\/natgeo\/posts\/10154212815083951\" class=\"fb-xfbml-parse-ignore\">\n<p>Inhumane and unsafe, snake wine is often made by drowning a live snake in alcohol. Before you purchase a gift abroad, here are a few things to know.<\/p>\nPosted by <a href=\"https:\/\/www.facebook.com\/natgeo\/\">National Geographic<\/a> on\u00a0<a href=\"https:\/\/www.facebook.com\/natgeo\/posts\/10154212815083951\">Wednesday, December 21, 2016<\/a><\/blockquote>\n<\/div>\n<\/div>"
                postsCtrl.instagram = "<div data-oembed-url=\"https:\/\/www.instagram.com\/p\/BOTfVSFDgn-\/?taken-by=natgeo&amp;hl=en\">\n<div style=\"max-width:320px;margin:auto;\"><!-- You're using demo endpoint of Iframely API commercially. Max-width is limited to 320px. Please get your own API key at https:\/\/iframely.com. -->\n<blockquote class=\"instagram-media\" data-instgrm-version=\"7\" style=\" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);\">\n<div style=\"padding:8px;\">\n<div style=\" background:#F8F8F8; line-height:0; margin-top:40px; padding:50.0% 0; text-align:center; width:100%;\">\n<div style=\" background:url(data:image\/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAABGdBTUEAALGPC\/xhBQAAAAFzUkdCAK7OHOkAAAAMUExURczMzPf399fX1+bm5mzY9AMAAADiSURBVDjLvZXbEsMgCES5\/P8\/t9FuRVCRmU73JWlzosgSIIZURCjo\/ad+EQJJB4Hv8BFt+IDpQoCx1wjOSBFhh2XssxEIYn3ulI\/6MNReE07UIWJEv8UEOWDS88LY97kqyTliJKKtuYBbruAyVh5wOHiXmpi5we58Ek028czwyuQdLKPG1Bkb4NnM+VeAnfHqn1k4+GPT6uGQcvu2h2OVuIf\/gWUFyy8OWEpdyZSa3aVCqpVoVvzZZ2VTnn2wU8qzVjDDetO90GSy9mVLqtgYSy231MxrY6I2gGqjrTY0L8fxCxfCBbhWrsYYAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;\">\u00a0<\/div>\n<\/div>\n\n<p style=\" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;\"><a href=\"https:\/\/www.instagram.com\/p\/BOTfVSFDgn-\/\" style=\" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none;\" target=\"_blank\">A photo posted by National Geographic (@natgeo)<\/a> on <time datetime=\"2016-12-22T03:35:07+00:00\" style=\" font-family:Arial,sans-serif; font-size:14px; line-height:17px;\">Dec 21, 2016 at 7:35pm PST<\/time><\/p>\n<\/div>\n<\/blockquote>\n<script async=\"\" defer=\"defer\" src=\"\/\/platform.instagram.com\/en_US\/embeds.js\"><\/script><\/div>\n<\/div>\n\n<p>\u00a0<\/p>";
                postsCtrl.youtube = "<div data-oembed-url=\"https:\/\/youtu.be\/G51LtqmZKto\">\n<div style=\"max-width:320px;margin:auto;\"><!-- You're using demo endpoint of Iframely API commercially. Max-width is limited to 320px. Please get your own API key at https:\/\/iframely.com. -->\n<div>\n<div style=\"left: 0px; width: 100%; height: 0px; position: relative; padding-bottom: 56.2493%;\"><iframe allowfullscreen=\"\" frameborder=\"0\" src=\"https:\/\/www.youtube.com\/embed\/G51LtqmZKto?wmode=transparent&amp;rel=0&amp;autohide=1&amp;showinfo=0&amp;enablejsapi=1\" style=\"top: 0px; left: 0px; width: 100%; height: 100%; position: absolute;\" tabindex=\"-1\"><\/iframe><\/div>\n<\/div>\n<\/div>\n<\/div>\n\n<p>\u00a0<\/p>\n<\/div>\n      \n<\/div>"
                postsCtrl.slider = "<div class=\"slick-slider\">\n \n <div>Service Slide 1<\/div>\n \n <div>Service Slide 2<\/div>\n \n <div>Service Slide 3<\/div>\n \n <\/div>";
            });
}]);

app.service("postsService", function($http, $q) {
    function getPost(postsId) {
        var deferred = $q.defer()
        var url = 'https://jsonplaceholder.typicode.com/albums/' + postsId;
        $http({
                    method: 'GET', // GET OPTIONS
                    cache: true,
                    url: url,
                    headers: {
                        'Content-Type': 'application/json;charset=UTF-8'
                    }
                }).then(function(response) {
                    //your code when success
                    deferred.resolve(response);
                }, function(response) {
                    //your code when fails
                    deferred.reject(response);
                });
                return deferred.promise;
            }
            this.getPost = getPost;
        });

app.directive('compileAjax', function($compile) {
    return {
        restrict: 'A',
        replace: true,
        link: function(scope, elem, attrs) {
            scope.$watch(attrs.compileAjax, function(html) {
                elem[0].innerHTML = html;
                $compile(elem.contents())(scope);
            });
        }
    }
});

app.directive('slickSlider', function() {
    return {
        restrict: 'C',
        link: function(scope, elem, attrs) {
            $(elem).slick({
                // settings
            });
        }
    }
});
</script>
<script src="//connect.facebook.net/en_US/sdk.js#xfbml=1&amp;version=v2.5" 
async></script>  
<script async="" defer="defer" src="//platform.instagram.com/en_US/embeds.js"></script>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</head>
<body>
    <body ng-app="app" ng-controller="postsController as postsCtrl">
        <script type="text/ng-template" id="page1.htm">
            <h2>You're on Page 1</h2>
            <a href="#page1">Go to page 1</a>
            <a href="#page2">Go to page 2</a>
            <div compile-ajax="postsCtrl.twitter"></div>
            <div compile-ajax="postsCtrl.facebook"></div>
            <div compile-ajax="postsCtrl.instagram"></div>
            <div compile-ajax="postsCtrl.youtube"></div>
            <div compile-ajax="postsCtrl.slider"></div>
        </script>
        <script type="text/ng-template" id="page2.htm">
            <h2>You're on Page 2</h2>
            <a href="#page1">Go to page 1</a>
            <a href="#page2">Go to page 2</a>
            <div compile-ajax="postsCtrl.twitter"></div>
            <div compile-ajax="postsCtrl.facebook"></div>
            <div compile-ajax="postsCtrl.instagram"></div>
            <div compile-ajax="postsCtrl.youtube"></div>
            <div compile-ajax="postsCtrl.slider"></div>
        </script>

        <div ng-view></div>

    </body>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

Dou*_*low 1

您需要在加载嵌入的小部件后手动初始化它们的 JavaScript,因为小部件是在页面加载后添加的,因此不会被初始化。

\n\n

对于推特

\n\n
twttr.widgets.load();\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

如果内容动态插入到页面中(例如延迟加载内容或使用pushState在文章之间导航的技术),则需要请求 Twitter\xe2\x80\x99s 小部件 JavaScript 扫描新按钮和小部件,使用功能twttr.widgets.load()

\n
\n\n

对于Instagram

\n\n
instgrm.Embeds.process();\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

如果要与 HTML 代码分开加载库,可以使用参数调用 oEmbed 端点omitscript。这对于想要自行处理 embeds.js 脚本加载的网站非常有用。要手动初始化嵌入代码,您可以调用 JavaScript 函数instgrm.Embeds.process()

\n
\n\n

对于脸书

\n\n
FB.XFBML.parse(); \n
Run Code Online (Sandbox Code Playgroud)\n\n
\n

<fb:like>您可以使用此函数使用 XFBML 语法(例如)或 HTML5 语法(例如<div class="fb-like">)重新渲染社交插件

\n
\n\n

您必须追踪其他社交媒体嵌入的初始化代码......

\n\n

除非您想要在 html 中获取特定的角度绑定/指令,否则编译 html 没有任何意义。

\n\n

这是一个基本演示

\n