PATCH 请求不适用于模糊,而适用于按键
PATCH request does not work on blur, while does on keydown
我正在尝试创建一个内嵌编辑器,它将支持点击编辑和保存 enter/blur。环境包括 PHP v5.6、jQuery v3.1、Laravel v5.2 和 MySQL.
问题是,虽然使用 enter 保存有效,但使用 blur 保存无效。
Laravel DB:listen 保存输入:
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:listen 以节省模糊,请注意根本没有 "update" 查询:
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',
]);
}
您的主要问题似乎是您在错误的元素上(在 .inline-editbox
而不是 <input>
上收听了 keydown
事件。
但是,您的代码中也有很多重复和不必要的步骤,因此我重写了它以使其更清晰。
以下:
- 有一个单独的函数来执行 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()
。
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();
});
.inline-edit > input {
width: 100%;
}
.ajax {
border: 1px solid green;
}
<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>
我正在尝试创建一个内嵌编辑器,它将支持点击编辑和保存 enter/blur。环境包括 PHP v5.6、jQuery v3.1、Laravel v5.2 和 MySQL.
问题是,虽然使用 enter 保存有效,但使用 blur 保存无效。
Laravel DB:listen 保存输入:
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:listen 以节省模糊,请注意根本没有 "update" 查询:
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',
]);
}
您的主要问题似乎是您在错误的元素上(在 .inline-editbox
而不是 <input>
上收听了 keydown
事件。
但是,您的代码中也有很多重复和不必要的步骤,因此我重写了它以使其更清晰。
以下:
- 有一个单独的函数来执行 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()
。
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();
});
.inline-edit > input {
width: 100%;
}
.ajax {
border: 1px solid green;
}
<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>