PATCH请求对模糊不起作用,而在keydown上则起作用

时间:2016-08-10 12:20:45

标签: jquery ajax laravel blur

我正在尝试创建一个内联编辑器,它将支持点击和保存输入/模糊时的编辑。该环境包括PHP v5.6,jQuery v3.1,Laravel v5.2和MySQL。

问题是,使用输入作品保存时,模糊保存不会。

Laravel DB:听取保存输入:

2016-08-10 12:01:45: select * from `user` where `user`.`id` = '15' limit 1
2016-08-10 12:01:45: update `user` set `name` = '22222', `updated_at` = '2016-08-10 12:01:45' where `id` = '15'

Laravel DB:听取保存模糊,注意没有"更新"查询:

2016-08-10 11:21:53: select * from `user` where `user`.`id` = '15' limit 1

似乎模糊不会检测到<input>文本已更改。我该如何解决?

inline-edit.js

var edit = $(".inline-edit");

edit.click(function() {
    $('.ajax').html($('.ajax input').val());
    $('.ajax').removeClass('ajax');
    $(this).addClass('ajax');
    $OLDVAL = $.trim($(this).text());
    $(this).html('<input id="inline-editbox" type="text" value="' + $OLDVAL + '">');
    // focus and move cursor to the end of the editbox
    var inline_editbox = $('#inline-editbox');
    inline_editbox.focus();
    var editbox_value = inline_editbox.val();
    inline_editbox.val('');
    inline_editbox.val(editbox_value);
    // 
    inline_editbox.blur(function(event) {
        var formData = {
            tag: $(this).attr('id'),
            value: $('.ajax input').val(),
        };
        $.ajax({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
            },
            type: "PATCH",
            data: formData,
            dataType: 'json',
            success: function(data) {
                $('.ajax').html($('.ajax input').val());
                $('.ajax').removeClass('ajax');
            },
            error: function(xhr, status, error) {
                console.warn(xhr.responseText);
                alert(error);
            }
        });
    });
});

edit.keydown(function(event) {
    if (event.keyCode == 13) {
        var formData = {
            tag: $(this).attr('id'),
            value: $('.ajax input').val(),
        };
        $.ajax({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
            },
            type: "PATCH",
            data: formData,
            dataType: 'json',
            success: function(data) {
                $('.ajax').html($('.ajax input').val());
                $('.ajax').removeClass('ajax');
            },
            error: function(xhr, status, error) {
                console.warn(xhr.responseText);
                alert(error);
            }
        });
    }
});

Laravel route.php的一部分:

Route::patch ('user/{id}',      ['as'=>'user.patch',  'uses'=>'UserController@update_ajax']);

Laravel UserController.php的一部分:

function update_ajax($id, UserCreateFormRequest $request)
{
    $user = User::findOrFail($id);
    $tag  = $request->get('tag');
    if( $tag == 'name') {
        $user->update([
            'name'        =>    $request->get('value')
        ]);
    }

    if( $tag == 'email') {
        $user->update([
            'email'       =>    $request->get('value')
        ]);
    }

    if( $tag == 'isRegistered') {
        $user->update([
            'isRegistered'=>    $request->get('value')
        ]);
    }

    return response()->json([
        'status' => 'success',
        'msg' => 'Data created successfully',
    ]);
}

1 个答案:

答案 0 :(得分:0)

您的主要问题似乎是您在错误的元素上收听keydown事件(.inline-editbox而不是<input>)。

但是,您的代码中也存在大量重复和不必要的步骤,因此我将其重写为更清晰。

以下内容:

  • 有一个单独的函数来执行Ajax调用(这使得Ajax调用和其他代码更容易理解,更重要的是,更容易测试)
  • 使用jQuery的XHR承诺来实现应用程序逻辑和Ajax逻辑的分离
  • 通过.trigger()使用jQuery自定义事件,以便上传到服务器的数据可以集中在一个地方
  • 在服务器更新失败时恢复原始值(您可以实现其他错误行为)
  • 在值未更改时不会向服务器发送更新
  • 正确处理HTML特殊字符(引号,尖括号)(您的版本在此方面存在错误)

完整代码:

function patchUser(params) {
    return $.ajax({
        url: 'user/...',
        headers: {
            'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')
        },
        type: "PATCH",
        data: JSON.stringify(params),
        contentType: "application/json"
    }).fail(function(xhr, status, error) {
        console.warn(xhr.responseText);
        alert(error);
    });
}

$(".inline-edit").click(function () {
    var $inlineEdit = $(this),
        curentValue = $.trim($inlineEdit.text());

    $inlineEdit.empty().addClass('ajax');
    $('<input>')
        .val(curentValue)
        .appendTo($inlineEdit)
        .on("blur", function () {
            $(this).trigger("contentchange");
        })
        .on("keydown", function (e) {
            if (e.keyCode == 13) $(this).trigger("contentchange");
        })
        .on("contentchange", function () {
            var newValue = $(this).val();
            if (newValue === curentValue) {
                $inlineEdit
                    .text(curentValue)
                    .removeClass('ajax');
            } else {
                patchUser({
                    tag: $inlineEdit.attr('id'),
                    value: newValue
                }).done(function (data) {
                    $inlineEdit.text(data);
                }).fail(function () {
                    $inlineEdit.text(curentValue);
                }).always(function () {
                    $inlineEdit.removeClass('ajax');
                });
            }
        })
        .focus();
});

实时样本

单击以运行演示。我在这里用模拟替换了patchUser()

&#13;
&#13;
function patchUser(params) {
    var result = $.Deferred();
    result.resolve("Value saved: (" + params.value + ")");
    return result.promise();
}

$(".inline-edit").click(function () {
    var $inlineEdit = $(this),
        curentValue = $.trim($inlineEdit.text());

    $inlineEdit.empty().addClass('ajax');
    $('<input>')
        .val(curentValue)
        .appendTo($inlineEdit)
        .on("blur", function () {
            $(this).trigger("contentchange");
        })
        .on("keydown", function (e) {
            if (e.keyCode == 13) $(this).trigger("contentchange");
        })
        .on("contentchange", function () {
            var newValue = $(this).val();
            if (newValue === curentValue) {
                $inlineEdit
                    .text(curentValue)
                    .removeClass('ajax');
            } else {
                patchUser({
                    tag: $inlineEdit.attr('id'),
                    value: newValue
                }).done(function (data) {
                    $inlineEdit.text(data);
                }).fail(function () {
                    $inlineEdit.text(curentValue);
                }).always(function () {
                    $inlineEdit.removeClass('ajax');
                });
            }
        })
        .focus();
});
&#13;
.inline-edit > input {
  width: 100%;
}
.ajax {
  border: 1px solid green;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="inline-edit" id="name">User Name</div>
<div class="inline-edit" id="email">User Email</div>
<div class="inline-edit" id="isRegistered">User IsRegistered</div>
&#13;
&#13;
&#13;