本文介绍了Angular JS无法在页面/路线更改上呈现社交媒体小部件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm creating a Angular App which makes an ajax call to a Drupal CMS system to get some content. Some of this content includes widgets from Facebook, Twitter, Instagram and Youtube.

ajax调用通过postsControllerpostsService完成.

The ajax call is done with a postsController and postsService.

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

I'm having trouble getting these social media widgets to render correctly. I've got them to render correctly when some one goes directly to the page with the widgets but if they change the route (page view) the widgets won't load. I believe this is because the script the API uses only runs on the page load event.

起初,angular根本不渲染小部件,但是我做了两件事使它起作用.

At first angular didn't render the widgets at all but I did two things to get it working.

  1. 我将CDN链接放到了wach API的头部的API javascript中,例如/platform.twitter.com/widgets.js
  2. 一旦我使用名为compileAjax
  3. 的自定义指令更改了从Drupal获取的数据,便对它进行了角度重新编译.
  1. I put the CDN link to the API javascript in the head for wach API e.g. /platform.twitter.com/widgets.js
  2. I made angular re-compile the data I fetched from Drupal once it changed with a custom directive I named compileAjax

当用户更改视图/路线时,如何使它们呈现?

下面是html文档中的屏幕快照和代码示例,其中,问题在单个html文档中进行了复制.这些窗口小部件在页面加载时可以正确呈现,但是在您单击转到页面链接之一时无法正确显示.

Below is a screenshot and sample of the code in a html doc in which the issue is replicated in a single html doc. The widgets render correctly on page load but not when you click one of the Go to Page links.

<!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>

推荐答案

加载嵌入式小部件后,您需要手动对其进行初始化,因为这些小部件是在页面加载后添加的,因此未初始化.

You need to manually initialize the javascript for the embedded widgets after loading them, since the widgets are being added after page load and therefore not being initialized.

对于 Twitter :

twttr.widgets.load();

对于 Instagram :

instgrm.Embeds.process();

对于 Facebook :

FB.XFBML.parse(); 

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

You'll have to track down the init code for the other social media embeds...

除非您要拾取的html中有特定的角度绑定/指令,否则编译html毫无意义.

Compiling the html doesn't make any sense unless there are specific angular bindings/directives in the html that you want to pick up.

这是一个基本演示.

这篇关于Angular JS无法在页面/路线更改上呈现社交媒体小部件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 23:18