繁体   English   中英

切换按钮时保留滚动位置

[英]Retain scroll position when a button is toggled

我正在一个angularJS应用程序上工作,该应用程序有一个页面,使用ng-repeat在其中显示大约30个项目。 每个项目前面都有一个切换按钮(启用/禁用)。 使用当前的代码,我可以切换这些项目。 但是问题是,如果我向下滚动并切换至第25项,那么它将自动滚动至页面顶部。 如果现在向下滚动,则可以看到切换实际上已发生。
因此,现在的要求是确保在单击切换按钮后保留滚动位置。

请参阅下面的代码。

的HTML

<div id="eventTypes" class="panel-body">
    <div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
        <div class="row">
            <div class="col-md-9">{{item.itemName)}}</div>
            <div class="col-md-3">
                <input id="toggleEnabled" 
                       type="button" 
                       ng-class="{'btn-primary': item.enabled}" 
                       value="{{item.enabled ? 'enabled' : 'disabled'}}" 
                       ng-click="toggleEnabled(item)">
            </div>
        </div>
    </div>
    <div ng-if="spinner" class="spinner">
        <div class="spinner-container container1">
            <div class="circle1"></div>
            <div class="circle2"></div>
            <div class="circle3"></div>
            <div class="circle4"></div>
            </div>
        <div class="spinner-container container2">
            <div class="circle1"></div>
            <div class="circle2"></div>
            <div class="circle3"></div>
            <div class="circle4"></div>
        </div>
        <div class="spinner-container container3">
            <div class="circle1"></div>
            <div class="circle2"></div>
            <div class="circle3"></div>
            <div class="circle4"></div>
        </div>
    </div>
</div>

JS

(function () {
    'use strict';
    angular.module('myApp').controller('itemsController', function ($scope, itemsService) {
        var serviceError = function (errorMsg) {
            console.log(errorMsg);
            $scope.turnOffSpinner();
        };

        $scope.items = [];
        $scope.item = {};
        $scope.spinner = true;

        $scope.toggleEnabled = function (item) {
            $scope.turnOnSpinner();
            itemsService.toggleEnabled(item)
                .then(function () {
                    $scope.loaditems();
                });
        };

        $scope.loaditems = function () {
            itemsService.getitems().then(function (response) {
                $scope.items = response.data;
            }, serviceError);
            $scope.turnOffSpinner();
        };

        $scope.turnOnSpinner = function () {
            $scope.spinner = true;
        };

        $scope.turnOffSpinner = function () {
            $scope.spinner = false;
        };

        $scope.loaditems();
    });
}());

现在这是如何工作的,一旦我单击切换按钮,就会启用微调器。 同时,控制器将调用itemService.toggleEnabled()方法,该方法会对服务器进行ajax调用,以仅更改后端中项目的状态(已启用或禁用)。 成功更改状态并返回ajax调用后,将在控制器中调用$scope.loadItems()方法。 然后,此方法将执行另一个ajax调用以获取项目(现在具有已切换项目的更新状态)。 禁用微调器,然后将数据显示在UI上。 完成所有这些操作后,页面将滚动到顶部。 当我要切换列表中向下的项目时,这很烦人。 当我单击相应项目的切换按钮并且不向上滚动到顶部时,我希望页面显示在同一位置。

我是AngularJS的新手,在这方面的任何帮助都会非常有帮助。

看起来您的微调器方案是导致您出现问题的原因:

...
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
...
<div ng-if="spinner" class="spinner">
...

每当您单击按钮时,您都将在$scope.turnOnSpinner()时从DOM中删除ng-repeat每个元素。 这就是为什么它跳到顶部的原因。 它并不是真正的跳跃,只是没有足够的DOM元素来填充页面,使页面如此之短以至于滚动条消失了(即使只是一秒钟)。 然后,当微调器完成后,您的ng-repeat再次用DOM元素填充页面,从而导致滚动位置丢失。

因此,基本上,您想要解决的是一个不太理想的加载微调器实现的症状。

ng-if是在Angular中隐藏事物的“残酷”方式。 与“更软”的指令(例如ng-show / ng-hide相比,它的主要作用是将事物隐藏更长的时间。 解决此问题的一种方法是在每个按钮上都使用ng-disabled ,以防止用户在微调器处于活动状态时与其进行交互,而不是硬删除每个元素:

之前:

<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
    <div class="row">
        <div class="col-md-9">{{item.itemName)}}</div>
        <div class="col-md-3">
            <input id="toggleEnabled" 
                   type="button" 
                   ng-class="{'btn-primary': item.enabled}" 
                   value="{{item.enabled ? 'enabled' : 'disabled'}}" 
                   ng-click="toggleEnabled(item)">
        </div>
    </div>
</div>

后:

<div ng-repeat="item in items" class="panel-body">
    <div class="row">
        <div class="col-md-9">{{item.itemName)}}</div>
        <div class="col-md-3">
            <input id="toggleEnabled" 
                   ng-disabled="spinner"
                   type="button" 
                   ng-class="{'btn-primary': item.enabled}" 
                   value="{{item.enabled ? 'enabled' : 'disabled'}}" 
                   ng-click="toggleEnabled(item)">
        </div>
    </div>
</div>

我真正喜欢并使用的另一个解决方案是此Angular模块: https : //github.com/darthwade/angular-loading

您可以将其附加到页面中的任何元素上,它将在其上放置一个加载微调器,并阻止您与之交互,直到您执行了ajax或其他操作为止。

如果您不喜欢上述任何一种,请尝试将ng-repeat放入一个容器中,该容器可用于防止微调器启动时与元素进行交互:

<div class="container" ng-class="{'you-cant-touch-this': spinner}">
  <div ng-repeat="item in items" class="panel-body">
    <div class="row">
        <div class="col-md-9">{{item.itemName)}}</div>
        <div class="col-md-3">
            <input id="toggleEnabled" 
                   type="button" 
                   ng-class="{'btn-primary': item.enabled}" 
                   value="{{item.enabled ? 'enabled' : 'disabled'}}" 
                   ng-click="toggleEnabled(item)">
        </div>
    </div>
  </div>
</div>

现在,您可以通过某种方式设置样式,以防止交互,而不必从DOM中删除所有这些项:

.you-cant-touch-this {
  pointer-events: none;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM