angularjsrestng-messages

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?


Solution

  • 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;