Laravel& ajax:如何以简化的方式更新多个表单输入

时间:2015-01-03 04:37:17

标签: php jquery ajax laravel laravel-4

我有一个用户可以更新其详细信息的表单。此更新通过使用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: https://stackoverflow.com/questions/26960929/laravel-4-when-i-retrieve-info-from-database-into-input-text-1-extra-space-is-a/26961224?noredirect=1#comment42683960_26961224-->
        </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 。如何安排我的代码,以便更新已经集中注意的最新输入的信息?

修改

我想要的是只更新每个输入。为了达到这个目的,我已经在每个输入中设置了标识符,这样我可以轻松地获得最近聚焦的输入。但首先我需要检测输入文本中的值是否已更改(在此编辑表单中,每个输入显示先前从用户保存在数据库中的数据)。

因此,在聚焦功能之前,我添加了另一个函数来检测特定输入的变化(通过其ID属性),就像在fiddle中一样。最后,我决定不在这里使用focusout(),因为它结果令人讨厌,特别是如果你把鼠标放在任何输入中,post()函数将不可避免地调用,例如,即使我去另一个窗口或另一个标签。

所以这里是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');//https://stackoverflow.com/a/23266812/1883256, 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});//https://stackoverflow.com/a/13362942/1883256
                            //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');

最后的问题: 剩下的唯一问题是不会出现超时状态。例如,如果一小时没有任何操作,我尝试修改数据,没有任何反应。什么都没有更新。所以我必须再次刷新页面。这在Stackoverflow中不会发生,即使计算机已经“休眠”并且我再次唤醒它,我仍然可以在不刷新页面的情况下更新信息。怎么可能?在我的情况下,我该如何保持页面活着?

1 个答案:

答案 0 :(得分:1)

我希望我理解你...

首先,使您的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'; } } 属性即可。

{{1}}

(我也删除了最后一个返回语句,因为它永远不会到达)