31

在我“显示”它之后,我试图滚动到页面上的一个元素。IE 我有一个很长的用户列表,我将它们显示为一个列表。每个元素都有一个可以单击的编辑图标。单击时,我会显示页面顶部的用户表单。然后我想滚动到那个位置。

  // helper method to scroll
  $scope.scrollTo = function (id) {
    $location.hash(id);
    $anchorScroll();
  }

在编辑用户点击:

  $scope.editUser = function (user) {
    $scope.user = user; // set user
    $scope.setShowUserForm(true); // show edit form
    $scope.scrollTo('admin-form'); // scroll to the form
  }

这很好用,除了第一次。我检查了 DOM,我的“用户表单”元素在 DOM 中但被隐藏了,这就是我想要的。当我第一次单击编辑用户时,滚动不起作用。第一次失败后一切都很好。我不确定发生了什么变化。

我还将表单设置为默认显示,这样我就知道它在 DOM 中并且在我第一次单击编辑时可见。那也没有解决我的问题。因此,无论它是否在 DOM 中,是否隐藏第一次滚动都会失败。

知道我做错了什么吗?

编辑:

我想我知道发生了什么,但我不知道如何解决它。我在我的应用程序中使用路由。我有这样的路线:

/#/主 /#/管理员

我正在使用滚动到它的管理页面导致问题。这是我要滚动到的 html:

<div id="admin-form">
...
</div>

问题是当我使用 Angular 滚动时,它会将我的网址更改为:

/#/admin#admin-form

什么时候它似乎击中了路由控制器并重新加载了我的管理页面,这就是滚动没有发生的原因。一旦我在 /#/admin#admin-form url 上,滚动就可以工作,因为 angular 看不到我的路线发生变化并且不会重新加载页面。但是,如果我将我的 url 更改回 /#/admin 并单击执行滚动到 angular 的按钮再次将 url 更改为 /#/admin#admin-form。

我确信这是预期的,但我不知道如何解决它。或者如果我可以。

4

5 回答 5

65

Angulars 路由似乎接受了更改,在我的情况下这很糟糕,因为 scrollTo 将我重新路由到主管理页面。

滚动然后重置 $location.hash() 以便角度不会感知 url 的变化似乎有效。

 $scope.scrollTo = function (id) {
    var old = $location.hash();
    $location.hash(id);
    $anchorScroll();
    $location.hash(old);
  }


编辑

正如@theunexpected1 的评论中提到的那样1.4.0,Angular$anchorScroll允许您直接将 id 作为参数传递,而无需使用哈希更新 url:

$scope.scrollTo = function(id) {

  // Pass the 'id' as the parameter here, the page will scroll 
  // to the correct place and the URL will remain intact.
  $anchorScroll(id);
}
于 2013-08-28T14:11:12.850 回答
9

我发现如果我想滚动到特定元素,我对更新 url 以显示我要访问的 ID 不感兴趣(例如 www.something.com/#admin-form 中的#admin-form id)

所以要滚动而不更新我发现的url,你可以调用anchorscroll而不需要更新位置哈希。

$anchorScroll('admin-form');
于 2015-07-19T19:38:50.090 回答
4

供将来参考 - 以及任何来到这里时遇到相同滚动问题但不使用 ng-routes 滚动的人,@Ben_Lesh 的回答实际上非常有见地。

我正在使用

$location.hash(id)
$anchorScroll()

滚动,但也遇到了关于第一次点击不起作用的同样问题。我意识到问题是我第一次单击对象设置为可见,然后尝试滚动到它,但是在滚动时,该元素在页面上仍然不可见。然后在循环结束时,页面重新呈现。

我第二次单击时,该元素现在设置为可见,因此滚动工作正常。

解决方案是,在设置使元素可见的布尔值之后,调用

$timeout(function() {$scope.$apply()},0)

然后调用您的滚动功能。这样你就可以在滚动之前强制重新渲染。瞧!

于 2015-04-02T15:45:16.830 回答
2

我创建了一个 plunk 来展示这个问题。请注意您必须单击两次按钮才能显示消息?

http://plnkr.co/edit/oU3REYC2upvlPMc5ipBp?p=preview

于 2013-07-22T23:17:19.533 回答
1

你在我的博客上以及评论中发布了一个关于这个的问题。

在不查看您的所有代码的情况下,我只能猜测这一点,但我可以告诉您一些可能有帮助的事情:

  1. 您无法滚动到隐藏元素。
  2. 实际的滚动是由一个由 $anchorScroll 设置的 $watch 完成的,它在 $digest 期间进行处理。
  3. 无论您设置什么来显示/隐藏该表单元素,都在 $digest 的 $watch 中进行处理。

因此,在我看来,它正在尝试在处理值以显示表单之前处理滚动。为了解决这个问题,我会尝试重构您用于显示表单的代码,或者将您的 $anchorScroll 调用包装在 $timeout 中以确保它在节目观看后执行。

我希望这会有所帮助。

于 2013-07-18T12:58:11.020 回答