简体   繁体   中英

Angular x-editable setError not displaying validation errors

I am using angular x-editable in my project. http://vitalets.github.io/angular-xeditable/#editable-row

Anything works fine except of validation error displaying. Here is my HTML template:

<table class="table">
        <thead>
            <tr>
                <th>Name</th>
                <th>Width</th>
                <th>Length</th>
                <th>Sheets quantity</th>
                <th>Low price</th>
                <th>High price</th>
                <th>Currency</th>
                <th></th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="material in sheetMaterials">
                <td>
                    <span editable-text="material.name" e-name="name" e-form="form" e-required>
                        {{ material.name }}
                    </span>
                </td>
                <td>
                    <span editable-text="material.width" e-name="width" e-form="form" e-required>
                      {{ material.width }}
                    </span>
                </td>
                <td>
                    <span editable-text="material.length" e-name="length" e-form="form" e-required>
                        {{ material.length }}
                    </span>
                </td>
                <td>
                    <span editable-text="material.sheets" e-name="sheets" e-form="form" e-required>
                        {{ material.sheets }}
                    </span>
                </td>
                <td>
                    <span editable-text="material.priceLow" e-name="priceLow" e-form="form" e-required>
                        {{ material.priceLow }}
                    </span>
                </td>
                <td>
                    <span editable-text="material.priceHigh" e-name="priceHigh" e-form="form" e-required>
                        {{ material.priceHigh }}
                    </span>
                </td>
                <td>
                    <span editable-select="material.currency"
                          e-ng-options="s.value as s.text for s in currencies"
                          e-name="currency"
                          e-form="form"
                          e-required>
                        {{ showCurrency( material ) }}
                    </span>
                </td>
                <td style="white-space: nowrap">
                    <form editable-form name="form"
                          onaftersave="updateSheetMaterial( $data, material._id, form )"
                          ng-show="form.$visible"
                          class="form-buttons form-inline"
                          shown="inserted == material">
                        <button type="submit"
                                ng-disabled="form.$waiting"
                                class="btn btn-primary">
                            Save
                        </button>
                        <button type="button"
                                ng-disabled="form.$waiting"
                                ng-click="form.$cancel()"
                                class="btn btn-default">
                            Cancel
                        </button>
                    </form>
                    <div class="buttons" ng-show="!form.$visible">
                        <button class="btn btn-primary" ng-click="form.$show()">
                            Edit
                        </button>
                        <button class="btn btn-danger" ng-click="removeSheeteMaterial( materials, $index )">
                            Delete
                        </button>
                    </div>  
                </td>
            </tr>
        </tbody>
    </table>
    <button class="pull-right btn btn-primary" ng-click="createSheetMaterial()">Add</button>

Here is a controller where I handle form behaviour:

angular.module( 'client' )
.controller(
    'materialController',
    [
        '$scope',
        '$filter',
        'sheetMaterialFactory',
        function(
            $scope,
            $filter,
            sheetMaterialFactory
        ){
            /**
             * index action
             * @return void
             */
            $scope.index = function(){
                $scope.currencies = [
                    { value: 'RUB', text: "Р" },
                    { value: 'EUR', text: "€" },
                    { value: 'USD', text: "$" },
                ]
                sheetMaterialFactory.getList().then( function( materials ){
                    $scope.sheetMaterials = materials;
                });
                $scope.content = "partials/material.html";
            }

            $scope.showCurrency = function( material ){
                var selected = $filter('filter')( $scope.currencies, { value: material.currency });
                return ( material.currency && selected.length ) ? selected[ 0 ].text : 'Not set';
            }

            /**
             * update sheet material
             * @param data – object of material options
             * @param _id – unique id of material
             * @return void
             */
            $scope.updateSheetMaterial = function( data, _id, form ){
                data._id = _id;
                var action = data._id ? "update" : "create";
                sheetMaterialFactory
                    [ action ]( data )
                    .then( function( sheetMaterial ){
                        if( "update" == action ){
                            var collection = $scope.sheetMaterials;
                            collection = collectionService.updateObject( collection, sheetMaterial );
                        } else {
                            collection.push( sheetMaterial );
                        }
                    }, function( error ){
                        if( error.data.errors ){
                            angular.forEach( error.data.errors, function( errorData, field ){
                                form.$setError( field, errorData.message );
                            });
                        } else {
                            form.$setError( 'name', 'Неизвестная ошибка' );
                        }
                    });
            }

            /**
             * create sheet material
             * @return void
             */
            $scope.createSheetMaterial = function( data ){
                if( !data ){
                    var sheetMaterial = { name: "Some name" };
                    $scope.sheetMaterials.push( sheetMaterial );
                    return;
                }
            }


            $scope.index();
        }
    ]
);

I've checked all the minor details and see that form.$setError works perfect. Error text really assigned to form element. But it does not displaying after form submitted. If anyone knows how to fix it – your reply is appreciated.

I had similar problems, until I understood (actually read the docs) that validation of fields should be managed through onbeforesave . If you want to define validation for one or more elements, which was my case, you can do so by using onbeforesave on the editable-* elements like this:

// on template (using controller as ctrl)
<span editable-select="material.currency"
    e-ng-options="s.value as s.text for s in currencies"
    e-name="currency"
    e-form="form"
    onbeforesave="ctrl.validateNotEmpty($data)"
    e-required>
    {{ showCurrency( material ) }}
</span>

// on controller
vm.validateNotEmpty(val) {
    if (!val) {
        return "This is a required field";
    }
}

The validation method will be called and if it returns a string, then the form will remain open and the errors will be displayed as expected.

-- Update --

The above would apply to error-handling prior to sending the request. If the validation must be done server-side, then the usage of $setError is of course the right way to go. I just added validation to a form like this, and worked perfectly:

// on controller
vm.updateMethod = function() {
    return myHttpUpdateMethod(foo)
        .catch(function(errors) {
            // Extract field and error_msg
            $scope.form.$setError(field, error_msg);
            // very important, as we're catching the error reject the
            // promise here, to stop the form from closing.
            return $q.reject(errors);
        });
}

Here is a nice jsFiddle I found: http://jsfiddle.net/NfPcH/81/

But I had to use a catch instead of an error in my special case. If you also use a catch don't forget to return a reject, or else the form will close.

Well, it seems I found one crappy solution. Not the best one, but it works. Any form element displaying should be typed this way:

<span editable-text="material.name" e-name="name" e-form="form" e-required>
    {{ material.name || form.$editables[ 0 ].error }}
</span>

form.$editables[ 0 ].error – is a direct access to errorText for element number 0 in form elements array. Solution is bad because you have to watch manually the index of your element and any form changes will cause fixing elements indexes.

I've faced just the same problem.. Error is not showing because form closes.. And my solution is to use form.$setError(name, msg) AND throw ('Error')

So you should change this

if( error.data.errors ){
                            angular.forEach( error.data.errors, function( errorData, field ){
                                form.$setError( field, errorData.message );
                            });
                        } else {
                            form.$setError( 'name', 'Неизвестная ошибка' );
                        }

to this

    if( error.data.errors ){

      angular.forEach( error.data.errors, function( errorData, field ){
          form.$setError( field, errorData.message );
      });
   } else {
     form.$setError( 'name', 'Неизвестная ошибка' );
   }
     throw ('Error occurred!');

use throw to prevent form from closing..) Hope, it helps someone.

Cheers!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM