简体   繁体   中英

How show validation messages from REST service on screen with AngularJS?

I have a controller like this:

(function() {
'use strict';

angular
    .module('app.bookmark')
    .controller('BookmarkEdit', BookmarkEdit);

function BookmarkEdit(BookmarkService, $stateParams, $state) {

    var vm = this;
    vm.bookmark = {};
    vm.save = save;

    function save() {
        BookmarkService.insert(vm.bookmark).success(saveOk).error(saveFail);
    }

    /* Callbacks */

    // I ommited the saveOk method!

    function saveFail(data, status, headers, config){
        switch(status){
            case 401:   console.log('401');
                        break;

            case 422:   console.log('422');
                        angular.forEach(data, function(value, key){
                         // THE CODE SHOULD COME HERE
                        });
                        break;
        }
    }

}})();

My service is like this:

(function() {
'use strict';

angular
    .module('app.bookmark')
    .factory('BookmarkService', BookmarkService);

function BookmarkService($http){

        var url = 'api/bookmark';

        BookmarkService.insert = function(bookmark){
            return $http.post(url, bookmark);
        };

        return BookmarkService;

}})();

If I send an empty form, my REST service makes its validations and return (RESPONSE) a JSON like this:

[
{property:description, message:required}
{property:link, message:maxlength}
]

I'd like to know how to show these messagens below of respective field?

Below follows my HTML code:

<form name="bookmarkForm class="well" role="form">

<div class="form-group">
    <label>ID: </label>
    <span id="id-text" class="form-control-static">{{bookmark.bookmark.id}}</span>
</div>

<div class="form-group">
    <label for="description">Description</label> 
    <input id="description" type="text" class="form-control" ng-model="bookmark.bookmark.description" value="{{bookmark.bookmark.description}}">
    <div id="description-message" class="label label-danger"><!-- the message should come here if exists --></div>
</div>

<div class="form-group">
    <label for="link">Link</label> 
    <input id="link" type="text" class="form-control" ng-model="bookmark.bookmark.link" value="{{bookmark.bookmark.link}}">
    <div id="link-message" class="label label-danger"><!-- the message should come here if exists --></div>
</div>

<div class="form-group">
    <button id="save" class="btn btn-primary" ng-click="bookmark.save()">Save</button>
</div>
</form>

EDIT

Looking for ngMessages, I change the DIV's for message to:

<div class="label label-danger" ng-messages="bookmarkForm.description.$error">
     <div ng-messages-include="templates/messages.html"></div>
</div>

And the messages.html file is like this:

<p ng-message="required" class="label label-danger">Required field</p>
<p ng-message="minlength" class="label label-danger">Few letters</p>
<p ng-message="manlength" class="label label-danger">Too much letters</p>
<p ng-message="url" class="label label-danger">Invalid URL</p>

I changed the controller to show the validations messages when necessary:

case 422:   angular.forEach(data, function(value, key){
              // I set the field invalid
              vm.bookmarkForm[value.property].$setValidity(value.message, false);
            });
            break;

Now the problem is that the previous validations messages remain on the screen after submitting the form again and change the content of this field so that it becomes valid, even though other fields in error.

How to clear these messages on the controller every time you send the form data?

I highly recommend combining the use of ngMessages and some custom logic on the promise resolving to set the error states appropriately.

Here is a great example of the usage for ngMessages - http://www.yearofmoo.com/2014/05/how-to-use-ngmessages-in-angularjs.html

The easiest thing to do would be to assign the errors to members of your view model and then simply output those members in their respective divs.

Something like:

angular.forEach(data, function(value, key){
   if (value.property === "link") {
       vm.linkError = value.message; }
   else {
       vm.linkError = "" ;}
   if (value.property === "description") {
       vm.descriptionError = value.message; }
   else {
       vm.descriptionError = "" ;}

});

Not super elegant, but it would get the job done.

I solved this way:

case 422:
  angular.forEach(vm.bookmarkForm, function(value, i) {
    if (typeof value === 'object' && value.hasOwnProperty('$modelValue')) {
      vm.bookmarkForm[value.$name].$setValidity(Object.getOwnPropertyNames(value.$error)[0], true);
    }
  });

  angular.forEach(data, function(value, key) {
    vm.bookmarkForm[value.property].$setValidity(value.message, false);
  });
  break;

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