A Better $state.reload for the AngularJS UI-Router

原文

  http://mwop.net/blog/2014-05-08-angular-ui-router-reload.htm

While working on Apigility , several times I ran into an odd issue: after fetching new data via an API and assigning it to a scoped variable, content would flash into existence... and then disappear. Nothing would cause it to display again other than a browser reload of the page.

Setup

I have a page that lists a set of items. When you create an item, you push data to the API, and, when done, the new item should be in that list.

First try: append to list

My first attempt was just appending the data to the list.


service.create(data).then(function (newItem) {
    flash.success = 'Successfully created something';
    /* append new item to list */
    $scope.services.push(newItem);
});

This worked... until you left that screen and returned. At that point, the new item would be gone, even if I coded my ui-router states to force a cache refresh.

Refresh list

My next attempt was to write a routine that would do a cache refresh after creating the new item.


service.create(data).then(function (newItem) {
    flash.success = 'Successfully created something';
    service.fetchAll(var force = true).then(function (services) {
        $scope.services = services;
    });
});

This is when I started noticing the "flash of content" problem. Essentially, immediately after fetching the set of services, you'd see the new item appended... and then it would disappear.

$state.reload()

At this point, I figured I'd use the ui-router to force a refresh, specifically via$state.reload() .


service.create(data).then(function (newItem) {
	flash.success = 'Successfully created something';
	service.fetchAll(var force = true).then(function (services) {
		$scope.services = services;
		$state.reload();
	});
});

I tried both with and without setting the scoped variable. Initially, I thought it was working -- but, as it turned out, I missed a case. I tested every single time with at least one item already in the list -- and this approach worked. However, when I tried with the list not yet populated, failure once again.

Success: $timeout

Surprisingly, the least intuitive solution ended up working: introducing a delay.


service.create(data).then(function (newItem) {
	flash.success = 'Successfully created something';
	service.fetchAll(var force = true)
		.then(function (services) {
			$scope.services = services;
		}).then(function () {
			return $timeout(function () {
				$state.go('.', {}, { reload: true });
			}, 100);
		});
});

I have a few things to note about this. First, I moved the "reload" into its own promise. This was done to ensure it doesn't block on the scope assignment. Second, I introduce a $timeout call. This essentially gives the scope a chance to populate before the reload triggers. Some examples I saw did a 1ms timeout; I found in practice that this was not long enough; 100ms was long enough, and did not introduce a noticeable delay in UI responsiveness. Finally, you'll note this does not use $state.reload() . This is due to discovering that part of my problem is a known bug in $state.reload() , whereby state "resolve" configuration is not honored.

I hope this approach helps others -- I've found it to be robust and predictable.

l
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值