Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add a custom message to a formly field after submit

I have a formly form of which I do not know what validation errors I will receive in advance. So, my plan: submit the form to the server, get errors back if they exist, then add the error message to the field in question. My code is this:

/* global angular */
(function() {

  'use strict';

  var app = angular.module('formlyExample', [
    'formly',
    'formlyBootstrap',
    'ngAnimate',
    'ngMessages'
  ]);

  app.run(function(formlyConfig, formlyValidationMessages) {
    formlyConfig.extras.errorExistsAndShouldBeVisibleExpression = 'fc.$touched || form.$submitted';
  });

  app.config(function(formlyConfigProvider) {

    formlyConfigProvider.setWrapper({
      name: 'validation',
      types: ['input'],
      templateUrl: 'error-messages.html'
    });

  });

  app.controller('MainCtrl', function MainCtrl(formlyVersion) {
    var vm = this;
    // funcation assignment
    vm.onSubmit = onSubmit;
    vm.env = {
      angularVersion: angular.version.full,
      formlyVersion: formlyVersion
    };

    vm.model = {};
    vm.options = {};

    vm.fields = [{
      key: 'coolValue',
      type: 'input',
      templateOptions: {
        required: false,
        type: 'text',
        label: 'Cool Value'
      }
    }, ];

    vm.originalFields = angular.copy(vm.fields);

    // function definition
    function onSubmit() {
      //if (vm.form.$valid) {
      //    vm.options.updateInitialValue();
      //   alert(JSON.stringify(vm.model), null, 2);
      // }
    }
  });

})();
body {
  margin: 20px
}
.formly-field {
  margin-bottom: 26px;
}
.error-messages {
  position: relative;
}
.error-messages,
.message {
  opacity: 1;
  transition: .3s linear all;
}
.message {
  font-size: .8em;
  position: absolute;
  width: 100%;
  color: #a94442;
  margin-top: 2px;
}
.error-messages.ng-enter.ng-enter-active,
.message.ng-enter.ng-enter-active {
  opacity: 1;
  top: 0;
}
.error-messages.ng-enter,
.message.ng-enter {
  opacity: 0;
  top: -10px;
}
.error-messages.ng-leave,
.message.ng-leave {
  opacity: 1;
  top: 0;
}
.error-messages.ng-leave-active,
.message.ng-leave-active {
  opacity: 0;
  top: -10px;
}
<!DOCTYPE html>
<html>

<head>
  <!-- Twitter bootstrap -->
  <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.css" rel="stylesheet">

  <!-- apiCheck is used by formly to validate its api -->
  <script src="//npmcdn.com/api-check@latest/dist/api-check.js"></script>
  <!-- This is the latest version of angular (at the time this template was created) -->
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>

  <!-- This is the latest version of formly core. -->
  <script src="//npmcdn.com/angular-formly@latest/dist/formly.js"></script>
  <!-- This is the latest version of formly bootstrap templates -->
  <script src="//npmcdn.com/angular-formly-templates-bootstrap@latest/dist/angular-formly-templates-bootstrap.js"></script>

  <script src="https://rawgit.com/angular/bower-angular-messages/v1.4.4/angular-messages.js"></script>
  <script src="https://rawgit.com/angular/bower-angular-animate/v1.4.4/angular-animate.js"></script>

  <title>Angular Formly Example</title>
</head>

<body ng-app="formlyExample" ng-controller="MainCtrl as vm">
  <div>
    <form ng-submit="vm.onSubmit()" name="vm.form" novalidate>
      <formly-form model="vm.model" fields="vm.fields" options="vm.options" form="vm.form">
        <button type="submit" class="btn btn-primary submit-button">Submit</button>
        <button type="button" class="btn btn-default" ng-click="vm.options.resetModel()">Reset</button>
      </formly-form>
    </form>
  </div>

  <!-- Put custom templates here -->
  <script type="text/ng-template" id="error-messages.html">
    <formly-transclude></formly-transclude>
    <div ng-messages="fc.$error" ng-if="form.$submitted || options.formControl.$touched" class="error-messages">
      <div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc.$viewValue, fc.$modelValue, this)}}</div>
    </div>
  </script>
</body>

</html>

And a JSBin page: http://jsbin.com/nupumakata/edit?html,js,output

What I'm trying to do: as soon as you hit the submit button, a custom validation message should be added to the Cool Value field. Since I don't know beforehand what errors will appear, I can't configure messages beforehand. So this:

formlyValidationMessages.addTemplateOptionValueMessage('pattern', 'patternValidationMessage', '', '', 'Invalid Input');

Would not work. In the answer I'm looking for, the message is added from inside the Submit function and only shown after the submit button is pressed (no error is shown until the submit button is pressed). I can't find in the documentation for Formly how to do this. Can anyone help please?

like image 427
yesman Avatar asked Nov 08 '22 15:11

yesman


1 Answers

So what I've done is I've gone ahead and given the field a custom template as follows:

 formlyConfigProvider.setWrapper({
      name: 'inputWrapper',
  template: '<div ng-class="to.changeColor==\'red\'? \'redBorder\' : \'otherBorder\'"><formly-transclude></formly-transclude>{{to.keyVal}}</div>'
    });

The form elements are defined through a schema format to allow each element to be individually accessed.

vm.schema={
    "schema": {
        "coolValue" : [{
                "key": "coolValue",
                "type": "input",

          "wrapper": ['inputWrapper'],
                "templateOptions": {
                   "type" : "text",
                  "label": 'Cool Value',
                  "keyVal":"",
                  "changeColor":"green"
                }

         }]


    }

};

Finally, the onSubmit function

function onSubmit() {

//Do whatever you want here
//Let's say your server returns an error "iNVALID Credentials"
   var response={
  "error": {
    "errors": [
      {
        "domain": "global",
        "reason": "authError",
        "message": "Invalid Credentials",
        "locationType": "header",
        "location": "Authorization",
      }
    ],
    "code": 401,
    "message": "Invalid Credentials"
  }
};
vm.schema.schema.coolValue[0].templateOptions.changeColor="red";
      vm.schema.schema.coolValue[0].templateOptions.keyVal=response.error.message;

    }
  });

You can essentially pass any error message or response from the server here.

The CSS contains a class to add a red border to the field.You are free to disable this.Feel free to ping if you need anything in this area as well.

Here is a DEMO

like image 125
Satej S Avatar answered Nov 15 '22 12:11

Satej S