Facebook登录按钮没有出现在ui-view孩子中

时间:2014-08-15 17:14:01

标签: facebook angularjs angularjs-directive facebook-javascript-sdk

我正在用facebook sdk制作一个AngularJS应用程序。结构如下:

<html xmlns:fb="http://ogp.me/ns/fb#">
<head>
    <title>Reportes para Anunciantes</title>
    <meta charset="UTF-8">
    <script type="text/javascript" src="js/angular.min.js"></script>
    <script type="text/javascript" src="js/angular-ui-router.min.js"></script>
    <!-- more scripts here -->
    <script type="text/javascript" src="js/index.js"></script>
</head>
<body>
    <script type="text/javascript">
        window.fbAsyncInit = function() {
            FB.init({
                appId      : 'MYAPPID', //Have an actual app id in my source
                cookie     : true,  // enable cookies to allow the server to access
                // the session
                xfbml      : true,  // parse social plugins on this page
                version    : 'v2.0' // use version 2.0
            });

            angular.bootstrap(document, ['Application']);
        };

        // Load the SDK asynchronously
        (function(d, s, id) {
            var js, fjs = d.getElementsByTagName(s)[0];
            if (d.getElementById(id)) return;
            js = d.createElement(s); js.id = id;
            js.src = "//connect.facebook.net/es_LA/sdk.js";

            fjs.parentNode.insertBefore(js, fjs);
        }(document, 'script', 'facebook-jssdk'));
    </script>
    <div id="content" ui-view>
        Cargando API de Facebook ...
    </div>
</body>
</html>

在页面中,我在加载Facebook API后加载Angular。该网站使用xfbml作为登录按钮。

整个角度应用程序位于index.js:

var Application = angular.module(
    "Application",
    ['ui.router'],
    ['$stateProvider', function($stateProvider){
        //$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
        $stateProvider
            .state('notloggedin', {
                templateUrl: 'templates/notloggedin.html',
                controller: 'Application.NotLoggedIn'
            })
            .state('notauthorized', {
                templateUrl: 'templates/notauthorized.html',
                controller: 'Application.NotAuthorized'
            })
            .state('inapp', {
                templateUrl: 'templates/inapp.html',
                controller: 'Application.InApp'
            });
    }]
);

function FBStatusChecker($state){
    this._state = $state;
}
FBStatusChecker.prototype = {
    checkAndGo: function(response) { /* omitted - no issue here */ },
    /* omitted methods - no issue here */
    updateState: function(){
        var context = this;
        FB.getLoginStatus(function(response) {
            context.checkAndGo(response);
        })
    }
};
Application.StatusChangeService = Application.service('Application.FBStatusChecker', ['$state', FBStatusChecker]);

Application.directive("fbLoginButton", function() {
    return {
        restrict: 'E',
        link: function (scope, iElement, iAttrs) {
            console.log("your ass");
            if (FB) {
                console.log("is broken");
                FB.XFBML.parse(iElement[0]);
            }
        }
    }
});

/* omitted controllers - no issue here.
   two of them are empty, and one correctly updates the scope
   via $scope.$apply(...) for an asynchronous callback */

Application.run(['Application.FBStatusChecker', function(statusChecker){
    statusChecker.updateState();
}]);

让我们按部分分析:

  1. 该页面使用ui-router在应用程序状态之间切换。这按预期工作。只有在成功加载FB API后才会加载Angular(即我的模块正在运行)。
  2. 应用程序定义了三种状态,并且在run()中选择了其中一种状态。
  3. 我省略了控制器,因为两个是空的,第三个更新 - 没有问题 - 范围。
  4. 我省略了状态切换器服务方法(这有使用$state根据facebook状态切换到三种状态之一的任务)。
  5. 有一个名为directive的{​​{1}}。该指令必须被识别为“E”(lement),并且应与fbLoginButton匹配。该指令已成功匹配。
  6. 在使用AngularJS和ui-router之前,我没有生成按钮的问题。
  7. 最后,模板来了:

    notloggedin.html

    fb:login-button

    notauthorized.html

    <fb:login-button max_rows="1" size="xlarge" show_faces="false" auto_logout_link="false"></fb:login-button>
    Debes iniciar sesi&oacute;n en Facebook para continuar.
    

    inapp.html

    <fb:login-button max_rows="1" size="xlarge" show_faces="false" auto_logout_link="false"></fb:login-button>
    Debes autorizar la aplicaci&oacute;n para continuar.
    

    备注:还尝试了使用div而不是xfbml的HTML5解决方案。

    我的问题是:Facebook按钮没有显示。仅显示相应的文本。如果我在点击此页面时登录Facebook,我会被正确地重定向到预期状态,同时获取<span ng-if="name"> Bienvenido {{ name }}! </span> <span ng-if="!name"> Listando ... </span> 。其他状态也是如此,所以我没有特别针对图api的问题,而是使用xfbml。

    我的问题是:我错过了什么?该指令正在匹配,但似乎{{ name }}没有效果。我该如何解决?

1 个答案:

答案 0 :(得分:0)

显然 - 由于一个幸运的错误发现它 - .parse方法忽略当前元素,因此解析必须从父元素开始。到目前为止,该指令必须改为:

Application.directive("fbLoginButton", function() {
    return {
        restrict: 'E',
        link: function (scope, iElement, iAttrs) {
            if (FB) {
                FB.XFBML.parse(iElement[0].parent);
            }
        }
    }
});

只需添加.parent属性即可获取父DOM节点。

但是,如果此指令匹配的两个项目是兄弟(或使用具有相同功能的另一个指令),则可以运行两次。因此,在解析之后将元素记录在数组中,并在解析之前进行检查,这将是一个很好的解决方法,以避免进行两次解析。另一种选择是强制在每个州的控制器中解析到ui-view - 持有容器。后者将实现如下:

  1. 唯一的指令是基于属性的指令,例如: xfbml-parse元素中的ui-view(在我的情况下):

    Application.directive("fbLoginButton", function() {
        return {
            restrict: 'E',
            link: function (scope, iElement, iAttrs) {
                if (FB) {
                    FB.XFBML.parse(iElement[0].parent);
                }
            }
        }
    });
    

    无需实施其他指令。

  2. 之后,在xfbml-parse元素中使用ui-view指令。就我而言:

    <div id="content" ui-view xfbml-parse>
        Cargando API de Facebook ...
    </div>
    

    每次状态发生变化时都会运行link函数 所以:每次ui-view节点呈现时,都会解析XFBML。