在angularjs中滚动到

在angularjs中滚动到,angularjs,Angularjs,我试图在“显示”页面上的某个元素后滚动到该元素。也就是说,我有一个很长的用户列表,我将他们显示为一个列表。每个元素都有一个可单击的编辑图标。单击后,我将显示页面顶部的用户表单。然后我想滚动到那个位置 // helper method to scroll $scope.scrollTo = function (id) { $location.hash(id); $anchorScroll(); } 在“编辑用户”菜单上,单击: $scope.editUser =

我试图在“显示”页面上的某个元素后滚动到该元素。也就是说,我有一个很长的用户列表,我将他们显示为一个列表。每个元素都有一个可单击的编辑图标。单击后,我将显示页面顶部的用户表单。然后我想滚动到那个位置

  // 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,我的“user form”元素在DOM中,但是隐藏了,这就是我想要的。当我第一次单击编辑用户时,滚动不起作用。第一次失败后,一切都很好。我不知道是什么改变了

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

知道我做错了什么吗

编辑:

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

/#/主要 /#/管理员

这是我的管理页面,我使用的滚动,这是造成问题。以下是我要滚动到的html:

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

...
问题是当我使用angular滚动时,它会将我的url更改为:

/#/管理员#管理员表单

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


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

您在我的评论中也发布了一个关于此的问题

不看你所有的代码,我只能猜测这一点,但我可以告诉你一些可能有用的事情:

  • 无法滚动到隐藏元素
  • 实际的滚动由$anchorScroll设置的$watch完成,该$watch在$digest期间处理
  • 无论您设置如何显示/隐藏该表单元素,都会在$watch的$digest中进行处理
  • 所以在我看来,它试图在处理显示表单的值之前处理滚动条。为了解决这个问题,我会尝试重构用于显示表单的代码,或者在$timeout中包装$anchorScroll调用,以确保它在节目观看后执行


    我希望这会有所帮助。

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


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

    滚动然后重置$location.hash(),使angular不会察觉url中的更改,这似乎是可行的

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

    编辑

    正如@TheUnexpected 1在评论中提到的,由于
    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);
    }
    

    作为将来的参考——以及任何一个在这里遇到同样的滚动问题但没有使用ng路线滚动的人,@Ben_Lesh的回答实际上是非常有洞察力的

    我在用

    $location.hash(id)
    $anchorScroll()
    
    要滚动,也会遇到与第一次单击不工作相同的问题。我意识到问题在于,我第一次单击将对象设置为可见,然后尝试滚动到该对象,但在滚动时,该元素在页面上仍然不可见。然后在循环结束时,页面重新呈现

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

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

    $timeout(函数(){$scope.$apply()},0)


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

    我发现,如果我想滚动到某个特定元素,我对更新url以显示我要使用的Id不感兴趣(例如www.something.com/#admin form Id)

    因此,要滚动而不更新我发现的url,您可以直接调用anchorscroll,而无需更新位置哈希

    $anchorScroll('admin-form');
    

    这将有助于看到更多的代码。我想你是在指令范围内做这件事的?谢谢,我会看看我是否能得到一个复制问题的提琴贴。至于暂停时间,这只是一个最好的猜测,我想这需要多长时间?如果在show/digest完成时执行'show'调用时有回调就好了,但不要认为有回调。不,这只是一个“立即”超时:
    $timeout(function(){$anchorScroll();})
    angular的想法是在滚动之前强制angular处理$digest并显示表单。还有一件事:您的控制台中是否有任何错误?也许这真的很简单,比如你忘了注射$anchorScroll什么的?(只是一个想法,因为我看不到你的代码)我更新了问题。我可以看到发生了什么,但不知道如何修复它。你真的需要设置一个plunk或一些演示问题的东西。修复一个黑匣子真的很难。我可以告诉你:你提供的所有代码看起来都很好,在我设置的每个测试中都很好。谢谢,它对我很有用!为了这件事不得不做一件蠢事。我希望这个解决方案在AngularJS.org.+1中的文档旁边,直到现在。解决方案在1.4.0(参考:)下发布。这意味着$anchorScroll('hash')将在不更新位置哈希的情况下滚动,这对我来说更简单:
    $scope.scrollTo=$anchorScroll并使用