Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC Validation form with AngularJS

I'm with a project in MVC 4 and AngularJS (+ twitter bootstrap). I usually use in my MVC projects "jQuery.Validate", "DataAnnotations" and "Razor". Then I enable these keys in my web.config to validate properties of model on the client:

<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />

For example if I have in my model this:

[Required]
[Display(Name = "Your name")]
public string Name { get; set; }

With this Cshtml:

@Html.LabelFor(model => model.Name)
@Html.TextBoxFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)

The html result would:

<label for="Name">Your name</label>
<input data-val="true" data-val-required="The field Your name is required." id="Name" name="Name" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>

But now when I use AngularJS, I want to render maybe like this:

<label for="Name">Your name</label>
<input type="text" ng-model="Name" id="Name" name="Name" required />
<div ng-show="form.Name.$invalid">
   <span ng-show="form.Name.$error.required">The field Your name is required</span>
</div>

I do not know if there are any helper or "Data Annotation" to resolve this. I understand that AngularJS has many more features like:

<div ng-show="form.uEmail.$dirty && form.uEmail.$invalid">Invalid:
    <span ng-show="form.uEmail.$error.required">Tell us your email.</span>
    <span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
</div>

Well, specifically. I need some helper or "Data Annotation" to resolve the attributes (Data Annotation) for display on the client with AngularJS.

If it still does not exist, perhaps it is time to do, like RazorForAngularJS

Edit

I think perhaps the best way to work with ASP.NET MVC and AngularJS is do it (front-end) by hand (writing all the HTML by hand)

like image 557
andres descalzo Avatar asked Feb 23 '13 23:02

andres descalzo


4 Answers

As someone that's authored an ASP.Net/Angular website, I can tell you that you're going to be way better off stepping away from using Razor to render your HTML where you can.

In my projects I've set up one razor view to render my main page (I'm using a single page app written in Angular), then I have a folder of straight .html files that I use as my templates for Angular.

The rest is done in ASP.Net Web API calls in my case, but you can also use MVC action with JSON results.

As soon as I switched to this architecture, things went a lot more smoothly for me, development wise.

like image 151
Ben Lesh Avatar answered Nov 14 '22 17:11

Ben Lesh


I agree with blesh idea about stepping away from razor, but you can create some tools for creating pages more rapid. IMHO it is better to use razor features where they needed instead of removing it from out toolset.

BTW have a look at ngval. It brings data annotations to client side as angularjs validators. It has an html helper and an angular module. I have to mention that project is in early development stages.

like image 9
alisabzevari Avatar answered Nov 14 '22 16:11

alisabzevari


I wrote a directive to smooth out the transition from MVC to AngularJs. The markup looks like:

<validated-input name="username" display="User Name" ng-model="model.username" required>

Which behaves identically to Razor conventions, including delaying validation until after a field is modified. Over time, I've found maintaining my markup pretty intuitive and simple.

My article on the subject

Plinkr

like image 4
Jeff Dunlop Avatar answered Nov 14 '22 18:11

Jeff Dunlop


I think there are probably half a dozen ways to do what you want. Probably the easiest is to use an Angular directive that recognizes jquery.validation markup.

Here is such a project: https://github.com/mdekrey/unobtrusive-angular-validation

And here is another: https://github.com/danicomas/angular-jquery-validate

I haven't tried either because personally, I solved this problem by writing code to make MVC output angular validation attributes instead of jquery.validation.unobtrusive attributes.

A 3rd option is to rely only on server side validation. Though this is obviously slower, it may be your only option sometimes for more complex validation scenarios. In this case, you just have to write javascript to parse the ModelStateDictionary object that Web API controllers usually return. There are some examples out there on how to do that and integrate it into AngularJS's native validation model.

Here is some incomplete code to parse the ModelStateDictionary:

````

angular.module('app')
    .directive('joshServerValidate', ['$http', function ($http) {
        return {
            require: 'ngModel',
            link: function (scope, ele, attrs, c) {
                console.info('wiring up ' + attrs.ngModel + ' to controller ' + c.$name);
                scope.$watch('modelState', function () {
                    if (scope.modelState == null) return;
                    var modelStateKey = attrs.joshServerValidate || attrs.ngModel;
                    modelStateKey = modelStateKey.replace(attrs.joshServerValidatePrefix, '');
                    modelStateKey = modelStateKey.replace('$index', scope.$index);
                    modelStateKey = modelStateKey.replace('model.', '');
                    console.info('validation for ' + modelStateKey);
                    if (scope.modelState[modelStateKey]) {
                        c.$setValidity('server', false);
                        c.$error.server = scope.modelState[modelStateKey];
                    } else {
                        c.$setValidity('server', true);
                    }
                });
            }
        };
    }]);

````

I'm rather disappointed with the other answers provided here. "Don't do it" isn't such a great suggestion when you're trying to validate something a little more difficult than an email address.

like image 2
Josh Mouch Avatar answered Nov 14 '22 18:11

Josh Mouch