5

Angularjs has great infrastructure for form validation and showing error messages. But, I am in a situation that I have to show a warning message to a user in a specific scenario. Here is the diagram of my simple form
enter image description here
The form has required and pattern validation applied on both fields. In addition to this validation I want a warning message to be displayed to the user if VatAmount is not 20 percent of the InvoiceAmount. The warning will differ from validation in following aspects

  1. It will not prevent the form submission
  2. It will only appear if both fields (InvoiceAmount and VATAmount) are valid
  3. The warning should have a button or link that would read "Change and proceed". When user presses that button the warning message will hide and focus will be set to VATAmount field.

I believe this is a prefect use case for creating a directive. Actually, I have given it a try and put my effort in the form of a plunker. But my directive does not handle following cases

  1. It appears even if the fields involved in warning are invalid
  2. The show and hide functionality is not implemented (have no idea how to target it)

Here is the link to the plunker

Muhammad Adeel Zahid
  • 17,474
  • 14
  • 90
  • 155
  • 2
    Umm...... VAT is always 20% so why are you asking your users to calculate it (and risk getting it wrong). Just do the calculation yourself. – JK. May 23 '15 at 11:20
  • client's requirement is to ask it from the user. – Muhammad Adeel Zahid May 24 '15 at 18:25
  • @MuhammadAdeelZahid, I tend to agree with JK here, having the user enter the VAT is error prone; but if your client requires that VAT is entered by the user: could you not use a select tag instead: the user would select 20% in the list (only entry beside 'select the VAT') and the computer would then make the calculation – Manube May 24 '15 at 19:57
  • 2
    @Manube In this specific case, I tend to agree with you both. But the question is still valid. Like you may need to show warnings instead of errors in some scenarios i.e "difference b/w booking data and invoice date is more than 30 days". This is a warning rather than an error. isn't it? – Muhammad Adeel Zahid May 25 '15 at 06:27

2 Answers2

3

Your plunkr demo was on the right track; really you just needed to check for the special cases of when one of the values was empty.

I'd suggest calculating the fraction and storing it in the scope, and then watching that to see whether you should display your tax rate warning. Here's how to calculate the fraction. If either invoice.Amount or invoice.VAT is empty, the fraction will be set to null.

if (amt == null || vat == null) {
    $scope.warning.fraction = null;
    return;
}
$scope.warning.fraction = vat / amt;

This works because those properties will be set to undefined if the user doesn't enter a valid number due to your use of ng-pattern.

However, while it's nice to encapsulate this in a directive, you don't need to compile the template yourself. Just use the built-in ng-transclude directive. Then you can include a button that references the current scope like this:

     <vat-warning>
       Vat Amount is not 20%.
       <button ng-click="invoice.VAT = invoice.Amount / 5">change</button>
     </vat-warning>

Your directive would contain this declaration:

    transclude: true,
    template: '<span class="alert-warning" ng-show="warning.show" ng-transclude></span>'

Plus a controller to update the directive's local scope to manipulate the warning object. Here's an updated demo.

z0r
  • 8,185
  • 4
  • 64
  • 83
  • This is almost what I want. The only thing is that I do not want to calculate VAT when user presses the change button. I need to just put the focus on second input (accepting VAT). Any idea how I would do that? Do I need to create a directive for that as well? – Muhammad Adeel Zahid May 24 '15 at 18:30
  • I was also wondering that the warning message does not show up when either field is in error and from the code I do not see anything that says "Do not show warning when there is an error". comments please – Muhammad Adeel Zahid May 24 '15 at 18:32
  • @MuhammadAdeelZahid I updated the answer to explain why the warning isn't shown when an input is invalid. – z0r May 25 '15 at 14:24
  • @MuhammadAdeelZahid To focus the VAT field, I would use a [*separate* directive that waits for an event](http://stackoverflow.com/a/18295416/320036). Just emit the event when the user clicks on the button. If you do this, you can reuse the `focusOn` directive in other parts of your application. – z0r May 25 '15 at 14:26
  • it is getting very strange. I used this solution in my application but it gives me following error Error: [ngTransclude:orphan] http://errors.angularjs.org/1.3.14/ngTransclude/orphan?p0=%3Cspan%20class%3D%22alert-warning%22%20data-ng-show%3D%22warning.show%22%20ng-transclude%3D%22%22%3E – Muhammad Adeel Zahid Jun 10 '15 at 14:32
  • the error appears only once after that the directive works as expected. The error do not show up in plunkr or when I try to put it up in a small application to show proof of concept – Muhammad Adeel Zahid Jun 10 '15 at 14:33
  • any idea what could be the problem? – Muhammad Adeel Zahid Jun 10 '15 at 14:34
1

You need to calculate visibility of vat-warning tag in controller on basis of $error.required and $error.pattern of invoiceAmount and vatAmount and then use it as below:

$scope.isInvoiceAmountInvalid = function () {
  var error = $scope.invoiceForm.invoiceAmount.$error;
  var required = error.hasOwnProperty("required") && error.required;
  var pattern = error.hasOwnProperty("pattern") && error.pattern;
  console.log("Inside isInvoiceAmountInvalid", error, required, pattern);
  return (required || pattern);
};

$scope.isVatAmountInvalid = function () {
  var error = $scope.invoiceForm.vatAmount.$error;
  var required = error.hasOwnProperty("required") && error.required;
  var pattern = error.hasOwnProperty("pattern") && error.pattern;
  console.log("Inside isVatAmountInvalid", error, required, pattern);
  return (required || pattern);
};

Here is an updated plunker for the same

Prashant Pimpale
  • 10,349
  • 9
  • 44
  • 84
Yashika Garg
  • 2,346
  • 2
  • 15
  • 17