调用$ state.go后,ion-list不会刷新

时间:2015-01-09 03:35:25

标签: angularjs ionic-framework angular-ui-router

我正在使用本教程学习AngularJS和离子框架:

http://www.htmlxprs.com/post/12/tutorial-on-using-parse-rest-api-and-ionic-framework-together

一切正常,直到我在createTodo状态下创建一个新项目,然后调用$ state.go('todos')返回我的项目列表,这里是创建Todo控制器的代码:

.controller('TodoCreateController', ['$scope', 'Todo', '$state', function($scope, Todo, $state) {
    $scope.todo = {};

    $scope.create = function() {
        Todo.create({content: $scope.todo.content}).success(function(data) {
            $state.go('todos', {}, {reload: true});
        });
    }
}])

以下是项目列表控制器的代码:

.controller('TodoListController', ['$scope', 'Todo', '$state', function($scope, Todo) {
    Todo.getAll().success(function(data) {
        $scope.items = data.results;
    });

    $scope.deleteItem = function(item) {
        Todo.delete(item.objectId);
        $scope.items.splice($scope.items.indexOf(item), 1);
    };
}])

以下是配置的状态

.config(function($stateProvider) {
    $stateProvider.state('todos', {
        url: '/todos',
        controller: 'TodoListController',
        templateUrl: 'views/todos.html'
    }).state('createTodo', {
        url: '/todo/new',
        controller: 'TodoCreateController',
        templateUrl: 'views/create-todo.html'
    });
})

当应用程序启动时,由于添加了最后一行并且主app.js中的.run方法结束(或者至少是我的理解),调用了TodoListController的方法:

.run(function($ionicPlatform, $state) {
    $ionicPlatform.ready(function() {

        if(window.cordova && window.cordova.plugins.Keyboard) {
            cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
        }
        if(window.StatusBar) {
            StatusBar.styleDefault();
        }
    });

    $state.go('todos');
})

我的问题是,一旦创建新项目并从TodoCreateController调用$ state.go('todos'),它就会将我带回项目列表,但新项目不在那里,方法永远不会调用TodoListController,因此会使列表过时。

如何在创建新项目后刷新“待办事项”状态中的列表?

4 个答案:

答案 0 :(得分:12)

我找到了一个相当优雅的解决方案:

在我的TodoListController中,我定义了一个这样的事件监听器:

$rootScope.$on('todo:listChanged', function() {
    $scope.updateList();
});

然后是updateList()方法

$scope.updateList = function() {
    Todo.getAll().success(function(data) {
        $scope.items = data.results;
    });
};

最后在TodoCreateController中,I $在创建项目后立即向上发送事件,并在更改状态之前立即发出事件

$scope.create = function() {
    Todo.create({content: $scope.todo.content}).success(function(data) {
        $scope.$emit('todo:listChanged');
        $state.go('todos');
    });
};

瞧!该列表相应地更新,如果我删除或更新列表项

,我现在可以使用相同的事件

答案 1 :(得分:3)

我遇到了这个和类似的问题,结果发现离子视图缓存通常是在返回缓存视图时不调用控制器代码的原因。

可能的解决方案

当将控制器代码分成一次性初始化代码时,在输入视图时,您通常会以这样的控制器结束:

// one-time initialization
$scope.updateList = function() {
    Todo.getAll().success(function(data) {
        $scope.items = data.results;
    });
};

$scope.$on('$ionicView.beforeEnter', function () {
    $scope.updateList();
});

这可以解决您的问题,而无需触发事件或向路线添加参数或数据。

<强>替代

可以通过不同方式禁用视图缓存:

  • cache: false添加到州定义
  • cache-view="false"添加到html <ion-view ...>
  • 使用$ionicConfigProvider.views.maxCache(0);禁用缓存(不建议这样做)

使用子状态时的陷阱

不是在你的情况下,但是如果在子状态中编辑/创建行(例如列表中的todo状态和创建新待办事项的todo.create),那么是来自ui-router的另一个问题:

todo.create导航到州todo时,您的超级州todo不会被执行&#34;,因为您已经在这种状态下来自todo.create。这是一个常见问题,可以通过本文其他答案中提供的一个更复杂的解决方案来解决。

答案 2 :(得分:2)

我的建议:

在你的配置中添加:

$stateProvider.state('todos', {
    url: '/todos',
    controller: 'TodoListController',
    templateUrl: 'views/todos.html',
    params : {
        updated : false
    }
})

使用ui-router here

了解params

然后在你的创建待办事项的$ state.go中,我会将其更改为:

$scope.create = function() {
    Todo.create({content: $scope.todo.content}).success(function(data) {
        $state.go('todos', {updated: true});
    });
}

在你的todo控制器中我会加上这个

if($stateParams.updated == true){
    Todo.getAll().success(function(data) {
        $scope.items = data.results;
    });
    $stateParams.updated = false;
}

这种方式不是指望重新加载来运行该函数,而是明确地寻找一个会触发重载的值。您也可以使用data对象而不是params对象执行相同的操作,并通过以下方式设置/检索值:

$state.get('createTodo').data.updated = true;
if($state.current.data.updated == true);

希望这有帮助!

另一种想法

将状态更改侦听器添加到组合中:

$rootScope.$on('$stateChangeSuccess', function(e, toState, toParams, fromState, fromParams) {
    if(fromState.name === 'createTodo' && toParams.updated == true){
        Todo.getAll().success(function(data) {
            $scope.items = data.results;
        });
        $stateParams.updated = false;
    }
}

答案 3 :(得分:2)

这对我有用:

$state.transitionTo('new-state', $state.$current.params, {reload: true});