离子列表在调用 $state.go 后不刷新
ion-list does not refresh after $state.go is called
我正在使用本教程学习 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'
});
})
当应用程序启动时,TodoListController 的方法被调用,这要归功于添加的最后一行和主程序中 .run 方法的结尾 app.js(或者至少这是我的理解):
.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 的方法,因此列表已过时。
如何在创建新项目后刷新处于'todos'状态的列表?
我的建议:
在您的配置中添加:
$stateProvider.state('todos', {
url: '/todos',
controller: 'TodoListController',
templateUrl: 'views/todos.html',
params : {
updated : false
}
})
阅读有关 ui-路由器的参数 here
然后在你创建的待办事项的 $state.go 中,我会将其更改为:
$scope.create = function() {
Todo.create({content: $scope.todo.content}).success(function(data) {
$state.go('todos', {updated: true});
});
}
我会在你的待办事项控制器中添加这个
if($stateParams.updated == true){
Todo.getAll().success(function(data) {
$scope.items = data.results;
});
$stateParams.updated = false;
}
这种方式而不是指望重新加载到 运行 您正在明确寻找将触发重新加载的值的函数。您也可以使用 data
对象而不是 params
对象和 set/retrieve 值来做同样的事情:
$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;
}
}
我找到了一个相当优雅的解决方案:
在我的 TodoListController 中,我定义了一个事件监听器,如下所示:
$rootScope.$on('todo:listChanged', function() {
$scope.updateList();
});
然后是 updateList() 方法
$scope.updateList = function() {
Todo.getAll().success(function(data) {
$scope.items = data.results;
});
};
最后,在 TodoCreateController 中,我在项目创建后立即向上发出事件,就在更改状态之前
$scope.create = function() {
Todo.create({content: $scope.todo.content}).success(function(data) {
$scope.$emit('todo:listChanged');
$state.go('todos');
});
};
瞧!列表相应地更新,如果我删除或更新列表项,我现在可以使用相同的事件
这对我有用:
$state.transitionTo('new-state', $state.$current.params, {reload: true});
我遇到过这个问题和类似的问题,结果证明 离子视图缓存 通常是返回缓存视图时不调用控制器代码的原因。
可能的解决方案
将控制器代码分成一次性初始化和代码运行进入视图时,通常会结束控制器看起来像这样:
// 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);
禁用缓存(不推荐这样做)
使用子状态时的陷阱
不是你的情况,但如果 子状态 中的 editing/creating 行(例如,状态 todo
和 todo.create
创建一个新的待办事项),ui-路由器还有一个问题:
当从todo.create
导航到状态todo
时,你的超状态todo
不会是"executed",因为你来的时候已经处于这个状态来自 todo.create
。这是一个常见问题,可以通过对此 post.
的其他答案中提供的更复杂的解决方案之一来解决。
我正在使用本教程学习 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'
});
})
当应用程序启动时,TodoListController 的方法被调用,这要归功于添加的最后一行和主程序中 .run 方法的结尾 app.js(或者至少这是我的理解):
.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 的方法,因此列表已过时。
如何在创建新项目后刷新处于'todos'状态的列表?
我的建议:
在您的配置中添加:
$stateProvider.state('todos', {
url: '/todos',
controller: 'TodoListController',
templateUrl: 'views/todos.html',
params : {
updated : false
}
})
阅读有关 ui-路由器的参数 here
然后在你创建的待办事项的 $state.go 中,我会将其更改为:
$scope.create = function() {
Todo.create({content: $scope.todo.content}).success(function(data) {
$state.go('todos', {updated: true});
});
}
我会在你的待办事项控制器中添加这个
if($stateParams.updated == true){
Todo.getAll().success(function(data) {
$scope.items = data.results;
});
$stateParams.updated = false;
}
这种方式而不是指望重新加载到 运行 您正在明确寻找将触发重新加载的值的函数。您也可以使用 data
对象而不是 params
对象和 set/retrieve 值来做同样的事情:
$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;
}
}
我找到了一个相当优雅的解决方案:
在我的 TodoListController 中,我定义了一个事件监听器,如下所示:
$rootScope.$on('todo:listChanged', function() {
$scope.updateList();
});
然后是 updateList() 方法
$scope.updateList = function() {
Todo.getAll().success(function(data) {
$scope.items = data.results;
});
};
最后,在 TodoCreateController 中,我在项目创建后立即向上发出事件,就在更改状态之前
$scope.create = function() {
Todo.create({content: $scope.todo.content}).success(function(data) {
$scope.$emit('todo:listChanged');
$state.go('todos');
});
};
瞧!列表相应地更新,如果我删除或更新列表项,我现在可以使用相同的事件
这对我有用:
$state.transitionTo('new-state', $state.$current.params, {reload: true});
我遇到过这个问题和类似的问题,结果证明 离子视图缓存 通常是返回缓存视图时不调用控制器代码的原因。
可能的解决方案
将控制器代码分成一次性初始化和代码运行进入视图时,通常会结束控制器看起来像这样:
// 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);
禁用缓存(不推荐这样做)
使用子状态时的陷阱
不是你的情况,但如果 子状态 中的 editing/creating 行(例如,状态 todo
和 todo.create
创建一个新的待办事项),ui-路由器还有一个问题:
当从todo.create
导航到状态todo
时,你的超状态todo
不会是"executed",因为你来的时候已经处于这个状态来自 todo.create
。这是一个常见问题,可以通过对此 post.