Laravel & ajax: 如何以简化的方式更新多个表单输入
Laravel & ajax: How to update several form inputs in a simplified way
我有一个表单,用户可以在其中更新他的详细信息。此更新是通过使用 jQuery focusout 函数和 Ajax 更新数据库来完成的。
在这个例子中,我有三个文本输入。我已经测试了第一个输入,当用户转到下一个输入时它会更新。更新该输入时会出现加载程序图标。
对于第一个输入,我创建了一个控制器及其相应的 JQuery 代码。
但是,如果我有 10 个输入的表单,我将不得不这样做 10 次。我的问题是:我该如何简化这个?所以我只需要编码一次。
表格如下:
<form role="form" class="form-horizontal" action="{{URL::route('user-edit-profile-post2')}}" method="post" id="formedit2">
<!---------------------------SECCIÓN USUARIOS---------------------->
<!-----Nombre de pila---------->
<div class="form-group @if ($errors->has('nombre_pila')) has-error @endif">
<label for="nombre_pila" class="col-sm-2 control-label">Nombre(s) de pila:</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="nombre_pila" name="nombre_pila" maxlength="45" value="@if(Input::old('nombre_pila')){{e(Input::old('nombre_pila'))}}@elseif(isset($nombrepila)){{$nombrepila}}@endif">
</div>
@if($errors->has('nombre_pila'))
<p class="help-block">{{$errors->first('nombre_pila')}}</p>
@endif
</div><!-- ----------fin nombre de pila ------------ -->
<div class="form-group @if ($errors->has('ap_paterno')) has-error @endif"><!--apellido paterno-->
<label for="ap_paterno" class="col-sm-2 control-label">Apellido paterno:</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="ap_paterno" name="ap_paterno" maxlength="45" value="{{ (Input::old('ap_paterno') ? e(Input::old('ap_paterno')) : (isset($ap_paterno) ? $ap_paterno : '')) }}"><!--Referencias:
</div>
@if($errors->has('ap_paterno'))
<p class="help-block">{{$errors->first('ap_paterno')}}</p>
@endif
</div><!-- ----------fin de apellido paterno ------------ -->
<div class="form-group @if ($errors->has('ap_materno')) has-error @endif"><!--apellido materno-->
<label for="ap_materno" class="col-sm-2 control-label">Apellido materno:</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="ap_materno" name="ap_materno" maxlength="45" value="@if(Input::old('ap_materno')){{e(Input::old('ap_materno'))}}@elseif(isset($ap_materno)){{$ap_materno}}@endif">
</div>
@if($errors->has('ap_materno'))
<p class="help-block">{{$errors->first('ap_materno')}}</p>
@endif
</div><!-- ----------fin de apellido paterno ------------ -->
<!------------------GUARDAR--------------------- -->
<div class="form-group"><!--Botón de guardar-->
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Guardar</button>
</div>
</div><!--Fin del botón de guardar-->
<!--------------Fin de GUARDAR ---------------->
<!--TOKEN-->
{{ Form::token() }}
</form>
在表格下方,我有这个 JQuery 代码:
<script type="text/javascript">
$('#nombre_pila').on('focusout',function(){
var editform = $('#formedit2').serializeArray();
var url = $("#formedit2").attr('action');//con esto se llama al controlador correspondiente!
$('#nombre_pila').addClass('loadinggif');
$.post(url, editform, function(data,status){
$('#nombre_pila').removeClass('loadinggif');
//alert(data);
if(data=='fail'){
alert('No se pudo actualizar el campo. Status:' + status);
}else if(data=='success'){
alert('Dato actualizado exitosamente! Status: ' + status);
}else if(status=='timeout'){
alert('El tiempo de espera se ha agotado. Recargue la página.');
}
});
});
</script>
控制器是:
public function postEditProfile2(){
//save data and send to form page or display a success message
//instanciando al usuario actual:
$id_user=Auth::user()->id;
$usuario=User::find($id_user);
$nombre_pila=Input::get('nombre_pila');
//preparando el dato para guardarlo
$usuario_data=array(
'nombre_pila'=>Input::get('nombre_pila')
);
// saving...
$usuario->fill($usuario_data);
if($usuario->save()){
return 'success';
}else{
return 'fail';
}
return 'posted: '.$nombre_pila;
}
到目前为止,我有这段代码可以更新第一个输入 nombre_pila,重点放在焦点上。现在我还有两个输入:ap_paterno 和 ap_materno。我如何安排我的代码,以便它更新已聚焦的最新输入的信息?
编辑:
我想要的是只更新每个输入。为了实现这一点,我在每个输入中设置了标识符,这样我可以很容易地获得最近关注的输入。但首先我需要检测输入文本中的值是否已更改(在此编辑表单中,每个输入显示用户先前保存在数据库中的数据)。
因此,在 focusout 函数之前,我添加了另一个函数来检测特定输入的变化(通过其 ID 属性),如 fiddle 中所示。最后,我决定不在这里使用 focusout(),因为它很烦人,特别是如果你将鼠标放在任何输入中,post() 函数将不可避免地被调用,例如,即使我转到另一个window 或到另一个选项卡。
所以这里是 JQuery 的编辑部分,它工作正常并且只在数据库中更新相应的输入值:
//Primero detectar si hubo cambios en un input dado
var timerid;
$("input").on("input",function(e){
var currentId = $(this).attr('id');
//alert('Current ID value is: '+currentId);
var value = $(this).val();
//preguntar si el dato del input en donde está el cursor ha cambiado:
if($(this).data('lastval')!=value){
$(this).data('lastval',value);
nuevoValor=$(this).val();
clearTimeout(timerid);
timerid=setTimeout(function(){
//change action
alert('vamos a actualizar la info...Identificador: '+currentId+' Nuevo valor:'+nuevoValor);
//AQUÍ PONEMOS EL PROCEDIMIENTO DE ACTUALIZACIÓN DE LA INFO DEL CAMPO CORRESPONDIENTE.
//var currentID = $('#formedit2 input').attr('id');// http://jsfiddle.net/xstqLkz4/59/, http://www.tequilafish.com/2007/12/04/jquery-how-to-get-the-id-of-your-current-object/
//var newValue = $(currentId).val();
alert('ID es: '+currentId+' and current value is: '+nuevoValor);
//var editform = {identifier:currentID,value:newValue};
var editform = $('#formedit2').serializeArray();
editform.push({name:'identifier',value:currentId});//
//alert(editform);
var url = $("#formedit2").attr('action');//con esto se llama al controlador correspondiente!
$(this).addClass('loadinggif');
$.post(url, editform, function(data,status){
$('#formedit2 input').removeClass('loadinggif');
//alert(data);
if(data=='fail'){
alert('Could not update the input field. Status:' + status);
$('#formedit2 input').removeClass('loadinggif');
}else if(data=='success'){
alert('Data updated successfully! Status: ' + status);
$('#formedit2 input').removeClass('loadinggif');
}else if(status=='timeout'){
alert('Time out. Please reload');
$('#formedit2 input').removeClass('loadinggif');
}else if(status=='error'){
alert('There has been an error. Try again later.');
$('#formedit2 input').removeClass('loadinggif');
}else{
$('#formedit2 input').removeClass('loadinggif');
alert(data);
}
});//end of post() function
//END OF UPDATING INFO PROCESS
},2500);
};
});//end of input part
这里是控制器,通过使用 switch 语句,控制器知道必须更新数据库中的哪个字段:
public function postEditProfile2(){
//save data and send to form page or display a success message
//instanciando al usuario actual:
$id_user=Auth::user()->id;
$usuario=User::find($id_user);
$identifier=Input::get('identifier');
//$nombre_pila=Input::get('nombre_pila');
$identificando=explode('_',$identifier);
$tabla=$identificando[0];
$num=end($identificando);
if($tabla=='usuario'){
switch ($num) {
case '01':
$usuario_data=array('nombre_pila'=>Input::get('nombre_pila'));
break;
case '02':
$usuario_data=array('ap_paterno'=>Input::get('ap_paterno'));
break;
case '03':
$usuario_data=array('ap_materno'=>Input::get('ap_materno'));
break;
default:
# code...
break;
}
// saving...*/
$usuario->fill($usuario_data);
/*$usuario->fill(Input::all());*/
if($usuario->save()){
return 'success';
}else{
return 'fail';
}
}else{
return 'error';
}
}//end of postEditProfile2() function
但现在的问题是 ajax-loader.gif,我将其添加为类的部分,$(this).addClass('loadinggif');
不再出现。为什么?有帮助吗?
已解决:
我没有正确使用 ajax 加载程序的选择器,它是一个简单的 + 号,但没有显示,如 here 所示,所以该行是:
$('#'+currentId).addClass('loadinggif');
最后一题:
剩下的唯一问题是超时状态不会出现。例如,如果一个小时过去了而没有任何操作,我尝试修改数据但没有任何反应。没有更新。所以我必须再次刷新页面。而在Whosebug中不会出现这种情况,即使电脑已经"sleeping",我再次唤醒它,我仍然可以在不刷新页面的情况下更新信息。这怎么可能?在我的案例中,我应该怎么做才能使页面保持活动状态?
希望我没听错...
首先,使您的 jQuery 代码通用,以便它适用于每个输入。您需要做的就是更改选择器:
$('#formedit2 input[type=text]').on('focusout',function(){
var editform = $('#formedit2').serializeArray();
var url = $("#formedit2").attr('action');//con esto se llama al controlador correspondiente!
$(this).addClass('loadinggif');
$.post(url, editform, function(data,status){
$(this).removeClass('loadinggif');
//alert(data);
if(data=='fail'){
alert('No se pudo actualizar el campo. Status:' + status);
}else if(data=='success'){
alert('Dato actualizado exitosamente! Status: ' + status);
}else if(status=='timeout'){
alert('El tiempo de espera se ha agotado. Recargue la página.');
}
});
});
如您所见,我更改了第一个选择器以匹配所有文本输入,并将引用 nombre_pila
的那些替换为 $(this)
。
之后,稍微更改一下控制器,使其填充传入模型的所有输入。只需确保正确设置模型中的 fillable/guarded
属性即可。
public function postEditProfile2(){
$id_user=Auth::user()->id;
$usuario=User::find($id_user);
$usuario->fill(Input::all());
if($usuario->save()){
return 'success';
}else{
return 'fail';
}
}
(我还删除了最后一个 return 语句,因为它永远不会到达)
我有一个表单,用户可以在其中更新他的详细信息。此更新是通过使用 jQuery focusout 函数和 Ajax 更新数据库来完成的。
在这个例子中,我有三个文本输入。我已经测试了第一个输入,当用户转到下一个输入时它会更新。更新该输入时会出现加载程序图标。
对于第一个输入,我创建了一个控制器及其相应的 JQuery 代码。
但是,如果我有 10 个输入的表单,我将不得不这样做 10 次。我的问题是:我该如何简化这个?所以我只需要编码一次。
表格如下:
<form role="form" class="form-horizontal" action="{{URL::route('user-edit-profile-post2')}}" method="post" id="formedit2">
<!---------------------------SECCIÓN USUARIOS---------------------->
<!-----Nombre de pila---------->
<div class="form-group @if ($errors->has('nombre_pila')) has-error @endif">
<label for="nombre_pila" class="col-sm-2 control-label">Nombre(s) de pila:</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="nombre_pila" name="nombre_pila" maxlength="45" value="@if(Input::old('nombre_pila')){{e(Input::old('nombre_pila'))}}@elseif(isset($nombrepila)){{$nombrepila}}@endif">
</div>
@if($errors->has('nombre_pila'))
<p class="help-block">{{$errors->first('nombre_pila')}}</p>
@endif
</div><!-- ----------fin nombre de pila ------------ -->
<div class="form-group @if ($errors->has('ap_paterno')) has-error @endif"><!--apellido paterno-->
<label for="ap_paterno" class="col-sm-2 control-label">Apellido paterno:</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="ap_paterno" name="ap_paterno" maxlength="45" value="{{ (Input::old('ap_paterno') ? e(Input::old('ap_paterno')) : (isset($ap_paterno) ? $ap_paterno : '')) }}"><!--Referencias:
</div>
@if($errors->has('ap_paterno'))
<p class="help-block">{{$errors->first('ap_paterno')}}</p>
@endif
</div><!-- ----------fin de apellido paterno ------------ -->
<div class="form-group @if ($errors->has('ap_materno')) has-error @endif"><!--apellido materno-->
<label for="ap_materno" class="col-sm-2 control-label">Apellido materno:</label>
<div class="col-sm-6">
<input type="text" class="form-control" id="ap_materno" name="ap_materno" maxlength="45" value="@if(Input::old('ap_materno')){{e(Input::old('ap_materno'))}}@elseif(isset($ap_materno)){{$ap_materno}}@endif">
</div>
@if($errors->has('ap_materno'))
<p class="help-block">{{$errors->first('ap_materno')}}</p>
@endif
</div><!-- ----------fin de apellido paterno ------------ -->
<!------------------GUARDAR--------------------- -->
<div class="form-group"><!--Botón de guardar-->
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Guardar</button>
</div>
</div><!--Fin del botón de guardar-->
<!--------------Fin de GUARDAR ---------------->
<!--TOKEN-->
{{ Form::token() }}
</form>
在表格下方,我有这个 JQuery 代码:
<script type="text/javascript">
$('#nombre_pila').on('focusout',function(){
var editform = $('#formedit2').serializeArray();
var url = $("#formedit2").attr('action');//con esto se llama al controlador correspondiente!
$('#nombre_pila').addClass('loadinggif');
$.post(url, editform, function(data,status){
$('#nombre_pila').removeClass('loadinggif');
//alert(data);
if(data=='fail'){
alert('No se pudo actualizar el campo. Status:' + status);
}else if(data=='success'){
alert('Dato actualizado exitosamente! Status: ' + status);
}else if(status=='timeout'){
alert('El tiempo de espera se ha agotado. Recargue la página.');
}
});
});
</script>
控制器是:
public function postEditProfile2(){
//save data and send to form page or display a success message
//instanciando al usuario actual:
$id_user=Auth::user()->id;
$usuario=User::find($id_user);
$nombre_pila=Input::get('nombre_pila');
//preparando el dato para guardarlo
$usuario_data=array(
'nombre_pila'=>Input::get('nombre_pila')
);
// saving...
$usuario->fill($usuario_data);
if($usuario->save()){
return 'success';
}else{
return 'fail';
}
return 'posted: '.$nombre_pila;
}
到目前为止,我有这段代码可以更新第一个输入 nombre_pila,重点放在焦点上。现在我还有两个输入:ap_paterno 和 ap_materno。我如何安排我的代码,以便它更新已聚焦的最新输入的信息?
编辑:
我想要的是只更新每个输入。为了实现这一点,我在每个输入中设置了标识符,这样我可以很容易地获得最近关注的输入。但首先我需要检测输入文本中的值是否已更改(在此编辑表单中,每个输入显示用户先前保存在数据库中的数据)。
因此,在 focusout 函数之前,我添加了另一个函数来检测特定输入的变化(通过其 ID 属性),如 fiddle 中所示。最后,我决定不在这里使用 focusout(),因为它很烦人,特别是如果你将鼠标放在任何输入中,post() 函数将不可避免地被调用,例如,即使我转到另一个window 或到另一个选项卡。
所以这里是 JQuery 的编辑部分,它工作正常并且只在数据库中更新相应的输入值:
//Primero detectar si hubo cambios en un input dado
var timerid;
$("input").on("input",function(e){
var currentId = $(this).attr('id');
//alert('Current ID value is: '+currentId);
var value = $(this).val();
//preguntar si el dato del input en donde está el cursor ha cambiado:
if($(this).data('lastval')!=value){
$(this).data('lastval',value);
nuevoValor=$(this).val();
clearTimeout(timerid);
timerid=setTimeout(function(){
//change action
alert('vamos a actualizar la info...Identificador: '+currentId+' Nuevo valor:'+nuevoValor);
//AQUÍ PONEMOS EL PROCEDIMIENTO DE ACTUALIZACIÓN DE LA INFO DEL CAMPO CORRESPONDIENTE.
//var currentID = $('#formedit2 input').attr('id');// http://jsfiddle.net/xstqLkz4/59/, http://www.tequilafish.com/2007/12/04/jquery-how-to-get-the-id-of-your-current-object/
//var newValue = $(currentId).val();
alert('ID es: '+currentId+' and current value is: '+nuevoValor);
//var editform = {identifier:currentID,value:newValue};
var editform = $('#formedit2').serializeArray();
editform.push({name:'identifier',value:currentId});//
//alert(editform);
var url = $("#formedit2").attr('action');//con esto se llama al controlador correspondiente!
$(this).addClass('loadinggif');
$.post(url, editform, function(data,status){
$('#formedit2 input').removeClass('loadinggif');
//alert(data);
if(data=='fail'){
alert('Could not update the input field. Status:' + status);
$('#formedit2 input').removeClass('loadinggif');
}else if(data=='success'){
alert('Data updated successfully! Status: ' + status);
$('#formedit2 input').removeClass('loadinggif');
}else if(status=='timeout'){
alert('Time out. Please reload');
$('#formedit2 input').removeClass('loadinggif');
}else if(status=='error'){
alert('There has been an error. Try again later.');
$('#formedit2 input').removeClass('loadinggif');
}else{
$('#formedit2 input').removeClass('loadinggif');
alert(data);
}
});//end of post() function
//END OF UPDATING INFO PROCESS
},2500);
};
});//end of input part
这里是控制器,通过使用 switch 语句,控制器知道必须更新数据库中的哪个字段:
public function postEditProfile2(){
//save data and send to form page or display a success message
//instanciando al usuario actual:
$id_user=Auth::user()->id;
$usuario=User::find($id_user);
$identifier=Input::get('identifier');
//$nombre_pila=Input::get('nombre_pila');
$identificando=explode('_',$identifier);
$tabla=$identificando[0];
$num=end($identificando);
if($tabla=='usuario'){
switch ($num) {
case '01':
$usuario_data=array('nombre_pila'=>Input::get('nombre_pila'));
break;
case '02':
$usuario_data=array('ap_paterno'=>Input::get('ap_paterno'));
break;
case '03':
$usuario_data=array('ap_materno'=>Input::get('ap_materno'));
break;
default:
# code...
break;
}
// saving...*/
$usuario->fill($usuario_data);
/*$usuario->fill(Input::all());*/
if($usuario->save()){
return 'success';
}else{
return 'fail';
}
}else{
return 'error';
}
}//end of postEditProfile2() function
但现在的问题是 ajax-loader.gif,我将其添加为类的部分,$(this).addClass('loadinggif');
不再出现。为什么?有帮助吗?
已解决: 我没有正确使用 ajax 加载程序的选择器,它是一个简单的 + 号,但没有显示,如 here 所示,所以该行是:
$('#'+currentId).addClass('loadinggif');
最后一题: 剩下的唯一问题是超时状态不会出现。例如,如果一个小时过去了而没有任何操作,我尝试修改数据但没有任何反应。没有更新。所以我必须再次刷新页面。而在Whosebug中不会出现这种情况,即使电脑已经"sleeping",我再次唤醒它,我仍然可以在不刷新页面的情况下更新信息。这怎么可能?在我的案例中,我应该怎么做才能使页面保持活动状态?
希望我没听错...
首先,使您的 jQuery 代码通用,以便它适用于每个输入。您需要做的就是更改选择器:
$('#formedit2 input[type=text]').on('focusout',function(){
var editform = $('#formedit2').serializeArray();
var url = $("#formedit2").attr('action');//con esto se llama al controlador correspondiente!
$(this).addClass('loadinggif');
$.post(url, editform, function(data,status){
$(this).removeClass('loadinggif');
//alert(data);
if(data=='fail'){
alert('No se pudo actualizar el campo. Status:' + status);
}else if(data=='success'){
alert('Dato actualizado exitosamente! Status: ' + status);
}else if(status=='timeout'){
alert('El tiempo de espera se ha agotado. Recargue la página.');
}
});
});
如您所见,我更改了第一个选择器以匹配所有文本输入,并将引用 nombre_pila
的那些替换为 $(this)
。
之后,稍微更改一下控制器,使其填充传入模型的所有输入。只需确保正确设置模型中的 fillable/guarded
属性即可。
public function postEditProfile2(){
$id_user=Auth::user()->id;
$usuario=User::find($id_user);
$usuario->fill(Input::all());
if($usuario->save()){
return 'success';
}else{
return 'fail';
}
}
(我还删除了最后一个 return 语句,因为它永远不会到达)