【问题标题】:UI focus bug, focus jumps back to last edited textbox after tabUI 焦点错误,选项卡后焦点跳回上次编辑的文本框
【发布时间】:2019-10-31 04:12:05
【问题描述】:

我有一个烦人的、有点奇怪的错误。我在淘汰赛中有一个网格,它有几列,其中一列是可编辑的。此列为每一行生成一个文本框输入。

当用户编辑一行,然后切换到下一行时,焦点将跳回到刚刚编辑的行。这只会发生一次,因此如果您再次按 Tab,您可以按 Tab 进入下一个框。

如果您不编辑文本框,则不会发生跳回行为。我很难看到究竟是什么导致了这种行为。

视图中剔除网格的代码:

<table class="table table-responsive table-striped center table-hover" style="clear: both; margin-bottom: 10px;" id="resultsTable">
                <thead>
                    <tr>
                        <th class="col-md-2"><b>Culture</b></th>
                        <th class="col-md-2"><b>Section</b></th>
                        <th class="col-md-2"><b>Name</b></th>
                        <th class="col-md-2"><b>Value</b></th>
                        <th class="col-md-2"><b>LastChangeOn</b></th>
                        <th class="col-md-2"></th>
                    </tr>
                </thead>
                <tbody data-bind='foreach: Items'>
                    <tr>
                        <td class="col-md-2">
                            <span data-bind="text: Culture"></span>
                        </td>
                        <td class="col-md-2">
                            <span data-bind="text: Section"></span>
                        </td>
                        <td class="col-md-2">
                            <span data-bind="text: Name"></span>
                        </td>
                        <td class="col-md-2">
                            <input type="text" data-bind="value: Value" />
                        </td>
                        <td class="col-md-2">
                            <span data-bind="text: LastChangeOn"></span>
                        </td>
                        <td class="col-md-2">
                            <span data-bind="text: Id, visible: false"></span>
                        </td>
                    </tr>
                </tbody>
            </table>

javascript代码:

<script type="text/javascript">
var _VM;
var initialLoad = true;

$(function () {
    LoadKnockoutContent(true);
});

$("#SearchButton").on("click", function (e) {
    _VM.moveToFirstPage();
});

IndexModel = function (initialData) {
    var _self = this;

    PagedViewModel.call(_self);

    _self.Items = ko.observableArray();

    _self.CurrentPage.subscribe(function (value) {
        $("#SearchCriteria_HiddenPage").val(value);

        LoadKnockoutContent(false, _self.Release);
    });

    _self.loadModelData = function (data) {
        _self.CurrentPage(data.CurrentPage);
        _self.PageSize = data.PageSize;
        _self.MaxPageIndex(data.PageCount);
        _self.Items(ToResourcesArray(data.Resources, _self));
    }

    _self.loadModelData(initialData);
};

ResourceModel = function (item, parent) {
    var _self = this;

    _self.Parent = parent;
    _self.Id = item.Id;
    _self.Culture = ko.observable(item.Culture);
    _self.Section = ko.observable(item.Section);
    _self.Name = ko.observable(item.Name);
    _self.Value = ko.observable(item.Value);

    _self.Value.subscribe(function (newValue) {
        // Send the new value to the backend
        SaveResource(newValue, item.Id);
    });

    if (!item.LastChangeOn == "") {
        _self.LastChangeOn = ko.observable(parseJsonDate(item.LastChangeOn).toPaddedDateTimeString());
    }
    else {
        _self.LastChangeOn = ko.observable(item.LastChangeOn);
    }
}

function ToResourcesArray(data, parent) {
    var items = ko.utils.arrayMap(data, function (item) {
        return new ResourceModel(item, parent);
    });

    return items;
}

    function LoadKnockoutContent(initialLoad, callback, callback2) {
    // Call to the back end, passing along the search criteria
    }

    function SaveResource(newValue, Id) {
        $.ajax({
            url: '@Url.Action("UpdateResource", "Resource")',
            data: JSON.stringify({ id: Id, newValue: newValue }),
            type: 'POST',
            cache: false,
            contentType: 'application/json;',
            dataType: 'json',
            success: function (data) {
                if (data.isSuccess) {
                    // Success, we need to reload here as well else the last changed on field is not updated in the grid overview
                    LoadKnockoutContent(false);
                } else {
                    alertify.error(data.message);
                    // Refresh the view else the value field will stay empty while it is not saved.
                    // A reload will show the grid again with the previous value.
                    LoadKnockoutContent(false);
                }
            },
            error: function (request, status, error) {
                alert(request.responseText);
            }
        });
    }
</script>

dd

【问题讨论】:

  • 您是否介意尝试将代码的大小减少到一个更便于人们回答并在未来对其他人有用的最小版本?
  • 是的,当然,我会尽量减少它
  • @WalterMacambira 我减少了视图代码,但我不确定是否可以进一步减少 JS 代码,因为我不知道问题可能出在哪一部分。我贴的JS代码全部用于Knockout Grid。
  • 在这些情况下,正如@WalterMacambira 所写,我们应该尝试禁用所有对于加载网格不是必需的代码。有时我更喜欢使用一个小的空项目(jsFiddle、CodePen 等)并逐渐添加代码,直到我回复错误为止。因此,在您的情况下,您可以尝试例如在 _self.Value.subscribe 中评论 SaveResource 行 (newValue, item.Id),但这只是一个假设。
  • 谢谢,我设法找到了导致该错误的原因。每次调用 save 方法后都会重新加载网格,而它只应在保存失败时发生。

标签: javascript asp.net-mvc knockout.js


【解决方案1】:

我已经解决了这个问题。

问题是网格在调用保存函数后被重新加载。这只应在保存失败时发生。如果每次保存后重新加载网格,那么当您使用 Tab 时,您将再次从 Grid 的第一行开始。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多