ui.router解析数据绑定在嵌套视图中不起作用

时间:2015-08-18 03:50:44

标签: angularjs data-binding angular-ui-router resolve

我正在尝试让我的父/子视图模板渲染一个值,该值应该在ui.router中的父路径中填充,但我对这个过程很新,无法理解我做错了什么。

我有一个包含用户名的导航栏,以及一个显示表单中所有用户数据的个人资料页面。我认为在路径中使用resolve会预先填充控制器中的数据对象,但有些东西是关闭的,因为我的输入字段能够使用来自同一对象的正确用户信息填充“ng-model”输入,但是我尝试在HTML模板中使用{{}}标记的所有地方都无法解析。

厂:

myApp.factory('userFactory', function($http, $q) {
    var service = {};

    delete $http.defaults.headers.common['X-Requested-With'];

    service.getCurrentUser = function() {
        var deferred = $q.defer();
        $http.get('/getmyuser') // returns a user Object, with "name", "profileImage", etc
        .success(function(response) {
            deferred.resolve(response);
        }).error(function(err) {
            deferred.reject(err);
        });
        return deferred.promise;
    }

    return service;
});

控制器:

function UserCtrl($scope, currentUser, userFactory) {
    $scope.currentUser = currentUser.currentUser;

    $scope.isLoggedIn = function() { // Works when checked in the same template as the elements that do not work.
        if ($scope.currentUser) return true;
        else return false;
    }

    $scope.isAdmin = function() { // When I check this with ng-show, it works.
        if ($scope.currentUser) {
            var roles = $scope.currentUser.roles;
            for (index = 0; index < roles.length; ++roles) {
                if (roles[index].name == "admin") return true;
            }
        }
        return false;
    }
}

模块:

var myApp = angular.module('myApp', ['ui.router'])
    .controller('userCtrl', ['$scope', 'currentUser', 'userFactory', UserCtrl])
    .config(function ($stateProvider,$urlRouterProvider, $locationProvider) {
        $locationProvider.html5Mode(true);

        $stateProvider
        .state('core', {
            url: '',
            abstract:true,
            resolve: {
                userFactory: 'userFactory',
                currentUser: function(userFactory) {
                    return userFactory.getCurrentUser().then(function(response) {
                        return { currentUser: response };
                    });
                }
            },
            views: {
                "nav@": {
                    templateUrl: '/api/v1/partials/nav',
                    controller: 'userCtrl'
                }
            }
        })
        .state('core.profile', {
            url: '/profile',
            views: {
                "contentArea@core": {
                    templateUrl: '/api/v1/partials/profile'
                }
            }
        });
    });

HTML文件1(index.html,作为ng-include包含在有效的HTML包装内,包含标题部分,正文部分,包括角度等的源包含):

<div ui-view="nav"></div>

HTML文件2(nav.html,其中大部分被省略,因为它是一个标准的bootstrap导航骨架...添加了一些感兴趣的部分。我的文档中没有任何ng-controller分配,因为这打破了解决注入):

<li ng-show="isLoggedIn()"> <!-- This works -->
    <a ui-sref="core.profile">
        Welcome, {{currentUser.name}}! <!-- This does not -->
    </a>
</li>
<!-- ... more code until the end of the nav bar -->
<div ui-view="contentArea"></div>

还有一个配置文件页面也是一个孩子,但输入正在处理那个,我不需要包含任何额外的内容,但是在该页面上也没有解析{{}},无论输入是什么自动的。我认为将所有初始化代码放在一个解决方案块中就可以解决这个问题,但显然我错过了一些东西。

任何帮助都会非常感激!

编辑:事实证明,ng-include(我用它作为将应用程序分解为更小模板的方式)是创建与userCtrl无关的独立范围,除非您想将其称为“$ parent“或将内容放入$ rootScope。

我重新构建了应用程序,不使用ng-include,现在我可以通过ng-bind和常规ol'$ scope访问我的绑定,而不是使用$ rootScope或者使用ng-includes独立范围。感谢所有人对此进行审核,并对错误方向的野鹅追逐表示抱歉。

2 个答案:

答案 0 :(得分:1)

所以有一些事情,你可能会重新使用这个解决方案,因为它是一个用户系统所以我会建议一个略有不同但相似的方法。

对于您的工厂,您应该在其中解析用户,然后将其存储,以便您不会重复请求。

myApp.factory('userFactory', function($http) {
    var service = {};

    delete $http.defaults.headers.common['X-Requested-With'];

    service.currentUser = null;

    service.init = function() {
        //you don't need $q here because $http returns a promise
        $http.get('/getmyuser').then(function(response) {
            service.currentUser = response.data;
        });
    };

    service.getCurrentUser = function() {
        return currentUser;
    };

    return service;
});

然后你的配置看起来像:

.state('core', {
    url: '',
    abstract:true,
    resolve: {
        userFactory: function(userFactory) {
            userFactory.init();
        }
    },
    views: {
        "nav@": {
            templateUrl: '/api/v1/partials/nav',
            controller: 'userCtrl'
        }
    }
});

.state('profile', {
    url: '/profile',
    parent: 'core',
    views: {
        "contentArea@core": {
            templateUrl: '/api/v1/partials/profile'
        }
    }
});

如您所见,导入此状态的方法是将其定义为父级。现在终于可以在控制器中执行此操作:

function UserCtrl($scope, userFactory) {
    $scope.currentUser = userFactory.getCurrentUser;
}

这只是概念,我没有对此进行测试,所以你可能需要稍微修改它,但希望这能让你朝着正确的方向前进。

答案 1 :(得分:0)

您必须只返回承诺:

resolve: {
            userFactory: 'userFactory',
            currentUser: function(userFactory) {
                return userFactory.getCurrentUser();
            }
        },

然后,在控制器中,它不再是

function UserCtrl($scope, currentUser, userFactory) {
$scope.currentUser = currentUser.currentUser;

但是

function UserCtrl($scope, currentUser, userFactory) {
$scope.currentUser = currentUser; // the object itself is directly available