我正在开发一个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的新手,在这方面的任何帮助都会非常有帮助。
答案 0 :(得分:2)
看起来你的微调方案正是导致你出现问题的原因:
...
<div ng-if="!spinner" ng-repeat="item in items" class="panel-body">
...
<div ng-if="spinner" class="spinner">
...
每当您点击按钮时,就会在ng-repeat
时从DOM中删除$scope.turnOnSpinner()
中的每个元素。这就是它似乎跳到顶端的原因。它不是真正的跳跃,只是没有足够的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;
}