2014-12-31 4 views
8

Ho un validatore asincrono che chiama un servizio restituirà 200 (OK) o 400 (BadRequest) con un messaggio.Validatore asincrono AngularJS - Messaggi di convalida dell'interfaccia utente dalla risposta del server

Desidero restituire il messaggio come messaggio di convalida, ma non riesco a capire come visualizzare il messaggio. Ho provato alcune cose senza successo.

<div ng-messages="searchFilterForm.search.$error"> 
    <small ng-message="valid">Invalid search filter. Reason: {{MY_BAD_REQUEST_RESPONSE_MESSAGE_GOES_HERE}}</small> 
</div> 
+0

Come si imposta asincrono validazione, quale validatore? – dfsq

+1

esattamente la stessa domanda che avevo, che era stata lasciata senza risposta, nulla di costruito per farlo, quindi ho fatto un trucco. vediamo se riceve questa risposta dagli esperti questa volta – harishr

+0

@dsfq, non dovrebbe avere importanza, ma qui c'è un link al mio validatore: https://github.com/exceptionless/Exceptionless.UI/blob/master/src/ componenti/validatori/search-filter-validator.js e un link al mio markup https://github.com/exceptionless/Exceptionless.UI/blob/master/src/components/search-filter/search-filter-directive.tpl .html # L10-L26 –

risposta

0

Ecco un jsfiddle: http://jsfiddle.net/javajunkie314/r6oyLe26/3/

L'idea è che le direttive myValidator e myErrorMessage sincronizzare il loro messaggio di errore tramite la direttiva myErrorHandler. Fastidiosamente, non riesco a trovare alcun modo per accedere al motivo passato a reject dal validatore.

Modifica: Ho aggiornato il violino. Ora myValidator utilizza due validatori asincroni. Ho anche creato un ValidatorPromise per gestire l'aggiornamento del controller myErrorHandler. Questo è come ho descritto nel mio commento qui sotto.

Il codice HTML:

<form ng-controller="testCtrl"> 
    <div my-error-handler=""> 
     <input type="text" name="foo" ng-model="foo.text" my-validator=""> 
     <div my-error-message=""></div> 
    </div> 
</form> 

La JavaScript:

(function() { 
    var app = angular.module('myApp', []); 

    /* Wraps a promise. Used to update the errorHandler controller when the 
    * validator resolves. */ 
    app.factory('ValidatorPromise', function ($q) { 
     return function (errorHandler, name, promise) { 
      return promise.then(
       // Success 
       function (value) { 
        // No error message for success. 
        delete errorHandler.error[name]; 
        return value; 
       }, 
       // Failure 
       function (value) { 
        // Set the error message for failure. 
        errorHandler.error[name] = value; 
        return $q.reject(value); 
       } 
      ); 
     }; 
    }); 

    app.controller('testCtrl', function ($scope) { 
     $scope.foo = { 
      text: '' 
     }; 
    }); 

    app.directive('myErrorHandler', function() { 
     return { 
      controller: function() { 
       this.error = {}; 
      } 
     }; 
    }); 

    app.directive('myValidator', function ($timeout, $q, ValidatorPromise) { 
     return { 
      require: ['ngModel', '^myErrorHandler'], 
      link: function (scope, element, attrs, controllers) { 
       var ngModel = controllers[0]; 
       var myErrorHandler = controllers[1]; 

       ngModel.$asyncValidators.test1 = function() { 
        return ValidatorPromise(
         myErrorHandler, 'test1', 
         $timeout(function() {}, 1000).then(function() { 
          return $q.reject('Fail 1!'); 
         }) 
        ); 
       }; 

       ngModel.$asyncValidators.test2 = function() { 
        return ValidatorPromise(
         myErrorHandler, 'test2', 
         $timeout(function() {}, 2000).then(function() { 
          return $q.reject('Fail 2!'); 
         }) 
        ); 
       }; 
      } 
     }; 
    }); 

    app.directive('myErrorMessage', function() { 
     return { 
      require: '^myErrorHandler', 
      link: function (scope, element, attrs, myErrorHandler) { 
       scope.error = myErrorHandler.error; 
      }, 
      /* This template could use ngMessages to display the errors 
      * nicely. */ 
      template: 'Error: {{error}}' 
     }; 
    }); 
})(); 
+1

Potrebbe essere più angolare idiomatico utilizzare un servizio condiviso anziché una direttiva per sincronizzare il messaggio di errore. –

+0

Grazie per aver postato la tua soluzione ma sembra anche una cattiva idea farlo in questo modo ... Cosa succede se il ngModel viene passato dopo myErrorHandler sull'array dei controller. Cosa succede se hai più validatori asincroni? La quantità di codice extra è appena salita. –

+0

L'array 'controllers' verrà passato nello stesso ordine dell'array' require', quindi non c'è motivo di preoccuparsene. Per quanto riguarda più validatori, è possibile mantenere un oggetto di messaggi di errore anziché una singola stringa, proprio come '$ error' funziona su' NgModelController'. –

0

ho preparato un plunker che penso fare quello che vuoi. Usa una versione modificata di ui-validate, ma penso che tu possa comunque avere l'idea.

Ho definito il servizio chiamato "remoteValidator". Ha un metodo 'validate' che simula il viaggio verso il server restituendo una promessa che rifiuta con un messaggio se il valore è 'cattivo'.

app.service("remoteValidator", function($q, $timeout) { 
    this.validate = function(value) { 
    return $q(function(resolve, reject) { 
     setTimeout(function() { 
     if (value === "bad") { 
      reject("Value is bad"); 
     } else { 
      resolve(); 
     } 
     }, 1000); 
    }); 
    } 
}); 

Poi ho definito nel controller un validatore che utilizzano tale servizio e catturare il messaggio di errore e tornare la promessa per il vostro validatore di scelta fare il lavoro.

$scope.remoteValAsync = function(value) { 
    var promise = remoteValidator.validate(value); 
    promise.then(function() { 
     delete $scope.errorMsg; 
    }, function(error) { 
     $scope.errorMsg = error; 
    }); 
    return promise; 
    }; 

In questo modo, quando si scrive 'cattivo' nell'InputBox asincrona, quando le promesse di risolvere, il messaggio di errore compare nel campo di applicazione insieme al nome validatori all'interno elenco $ error form.field..

un frammento del HTML:

<div class="input-group-inline"> 
    <input class="form-control" type="text" name="nextPassword" ng-model="passwordForm.nextPassword" 
      ui-validate-async="{ badValue: 'remoteValAsync($value)' }" /> 
     <p>Pending validations:</p> 
      <ul> 
      <li ng-repeat="(key, errors) in myForm.nextPassword.$pending track by $index">{{ key }}</li> 
      </ul> 
     <p>Bad validations:</p> 
      <ul> 
      <li ng-repeat="(key, errors) in myForm.nextPassword.$error track by $index">{{ key }}</li> 
      </ul> 
     <p>{{ errorMsg }}</p> 
</div> 

So droping il messaggio in 'errorMsg' non è il migliore. Potrebbe essere migliorato, ma devo entrare in una direttiva asincrona-asincrona.

Spero che aiuti.

1

Vorrei suggerire fare la movimentazione sul lato server eccezione globale, se errore si verifica quindi inviare successo come falsa con messaggio di errore

json.put("success", false); 
json.put("message",errorMessage); 

Altrimenti inviare JSON con successo come vero con valore

json.put("success", true); 
json.put("values",output); 

Quindi su UI side handle exception using

$.post(serverUrl,valuesJson) 
.success(function(responseData) { 
    var responseData = JSON.parse(responseData); 
    if(responseData.success){ 
     \\ write your logic 
    } else { 
     alert(responseData.message); 
    } 
}).fail(function(xhr, textStatus, errorThrown) { 
    //check for session out 
    if(xhr.status == 403) 
     alert("Your session is timed out.redirected to Login screen."); 
    // redirect to login  
}) 
.error(function(responseData){ 
    console.log(responseData); 
}); 
Problemi correlati