Angular x-editable setError not displaying validation errors

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

Everything works fine except for displaying a validation error. 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 the controller in which I handle the behavior of the form:

 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 checked all the small details and saw this shape. $ setError works fine. The error text is indeed assigned to the form element. But after submitting the form, it does not appear. If someone knows how to fix this, your answer will be appreciated.

+5
source share
3 answers

I had similar problems until I realized (actually read the documents) that field validation should be managed through onbeforesave . If you want to define validation for one or more elements, which was my business, you can do this using onbeforesave for editable elements *, for example:

 // 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, the form will remain open and errors will be displayed as expected.

- Update -

The above applies to error handling prior to sending a request. If the check should be done on the server side, then using $setError is, of course, the right way. I just added validation to a form like this and it 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 catch instead of error in my special case. If you also use catch , don't forget to return the reject, otherwise the form will close.

+3
source

Well, it looks like I found one shitty solution. Not the best, but it works. The display of any form element should be printed as follows:

 <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 direct access to errorText for element number 0 in the array of form elements. The solution is bad, because you have to manually view the index of your element, and any changes to the form will result in indices of the commit elements.

+2
source

I ran into the same problem. The error is not displayed because the form is closing. And my solution is to use form.$setError(name, msg) AND throw ('Error')

So you have to change this

 if( error.data.errors ){ angular.forEach( error.data.errors, function( errorData, field ){ form.$setError( field, errorData.message ); }); } else { form.$setError( 'name', ' ' ); } 

to that

  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 the form from closing.) Hope this helps someone.

Hurrah!

+1
source

Source: https://habr.com/ru/post/1200570/


All Articles