I'm using AngularJS in my MVC application and trying to use the best of both worlds. I really like how you can in MVC set up your validation logic in your viewmodels and generate client side validation with jQuery validation in your razor views with little effort. I use AngularJS to get the SPA behavior with routing etc, but when I create a razor view that I use to inject into a page with:
<div data-ng-view="data-ng-view"></div>
then the jQuery validation stops working, even though the script files is references on the page where the view is injected. See below for my razor view:
#model BandViewModel
<div data-ng-controller="App.BandCreateCtrl">
<form name="startBandForm">
#Html.ValidationSummary(true)
<br />
#Html.LabelFor(m => m.Name)
#Html.TextBoxFor(m => m.Name, new { data_ng_model = "band.Name" })
#Html.ValidationMessageFor(m => m.Name)
<br/>
<input data-ng-disabled="startBandForm.$invalid" type="submit" data-ng-click="createBand(band)" value="Create"/>
</form>
</div>
First of all, IMO using Razor to render your templates is fraught with peril, at best. Generally you want to use static HTML for your page and directive templates, and then retrieve and post data as AJAX to your API. The ASP.NET web API is really good at this, actually. If your underlying model has validation, then bad web API calls will throw an exception, which you can catch in your $http or $resource handler and show to the user. Mixing standard HTTP form posts with AngularJS will be... difficult.
To achieve what you want, I think someone (not me) would have to write the AngularJS equivalent to jQuery Unobtrusive Validation library, which itself is using the jQuery Validate plugin. Not trivial. I personally don't see drop-in Angular validation happening soon, especially since it has more to do with markup and less to do with a JS configuration object.
Possibly you could re-initialize the validation when the view has finished loading using the $viewContentLoaded event. But please don't.
It pains me that everywhere I've looked we get the same replies: "HTML should just be a template". Perhaps, but I'm just not ready to delegate everything to JavaScript
Instead of using the anonymous object for passing the HTML attributes, try using the Dictionary
#Html.TextBoxFor(m => m.Name, new Dictionary<string, object>(){{ "data_ng_model", "band.Name" }})
Make sure is
Dictionary<string, object>
And not
Dictionary<string, string>
Otherwise the constructor will confuse it for
object HtmlAttribute
Not as pretty though... but it works for the most part.
Lastly, take in mind that if you include AngularJS after jQuery, then it will use jQuery for selectors.
To anyone still looking for a solution to this problem , there is a simple way to make it work.
var currForm = $("#myForm");
currForm.removeData("validator");
currForm.removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse(currForm);
currForm.validate();
You could put this code in $viewContentLoaded or other places which are relevant in your code.
While I understand some of the views here which discourage MVC views being used as a templates for your Angular code. My reason being its not not a natural way of doing things in angular and hence there are chances that you will run into issues like this one. But if you benefit from using MVC views as templates its not a path to hell. IT works and can benefit you as well. I have 2 use cases in my project where using MVC views make a lot of sense.
My project actually has a requirement where a client can turn of the required validation on certain field , for this I use the MVC custom data annotation validator which allows me to add or remove the data annotation at the time of rendering the view using a single class , if you were to build the same flexibility in angular , you would have to write a lot more code. So MVC views work great here for me as Custom Data Annotations are triggerd by the DisplayFor and EditorFor helpers
We are heavily invested in Internationalization and while angular is great at other stuff internationalization is not its strong suite ( at the time of writing this atleast )I still feel the internationalization support in MVC with .RESX works great and has been here long . This again uses the data annotation power of the DisplayAttribute.
TLDR : MVC views as templates may give you a few unexpected problems but are worth it if you are really using the full power of the data annotation pipeline created by Microsoft.
Hopefully someone comes up with a Angular HTML Helpers library in the future this would be much simpler.
Maybe using Angular for validation can be less painful than you think. Using a couple of custom directives, you could easily get something quite close to Razor with markup as simple as:
<validated-input name=username display="User Name" ng-model=model.username required</validated-input>
Check out my sample here and its inspiration here. It only implements required and number at the moment, but customizing it should be easy.
You can use ngval library. It brings data annotations to client side as angularjs validation directives.
Related
I have a partial view which outputs a list of editors. Each editor in the list has a delete link, which is called using #Ajax.actionlink, like this:
if(Model.Any()){
<ul>
#foreach (var editor in Model)
{
<li>#editor.firstName #editor.lastName, #editor.emailAddress (#Ajax.ActionLink("Delete", "DeleteEditor", "EditorSurface", new { editorId = editor.id }, new AjaxOptions()))</li>
}
</ul>
}
I've included #using System.Web.Optimization; in my view and am calling the jquery unobtrusive ajax script from my view too:
#Scripts.Render("~/scripts/jquery.unobtrusive-ajax.min.js")
The issue is that when I view source, the rendered mark-up for my editor list items is like this:
<li>John Smith, johnsmith#example.com (Delete)</li>
I was a little disappointed to see the inline JavaScript in the delete links and was hoping for something a little 'cleaner' (possibly data attributes or something?). It strikes me this is going to be difficult to hook into (to provide confirmation messages etc).
Question is, is this the expected output of AJAX in ASP.NET MVC? I'm very new to this so not sure if I'm doing something wrong in my implementation.
Many thanks.
Yes, this is the markup the Ajax.* family of helpers produces. My recommendation in general, and especially in light of the fact that you don't want the on* attributes added, is to avoid these helpers like the plague. You'll have much cleaner and maintainable (though slightly more verbose) code handling AJAX yourself, i.e. just add a standard Html.ActionLink and then use jQuery to attach an event handler that calls the AJAX. Plus, when something goes wrong, as it almost inevitably does, you have full knowledge and control over the JavaScript that is running, rather than being at the mercy of some opinionated Microsoft dev.
i don't like auto-generated code so i made a decision to never use Asp.net MVC's Html Helpers, but i face a problem when it comes to save the value of an input after validation failed, so the value is saved when i use
#Html.TextBoxFor(m=>m.Name)
but it doesn't save the value when i write
<input type="text" name="Name"/>
so how can i have the same thing without using TextBoxFor Helper, and what does this helper do, that i haven't
i don't like auto-generated code so i made a decision to never use Asp.net MVC's Html Helpers
You are going to have a hell hard time doing ASP.NET MVC development if you do not use helpers and I am afraid that you will not get very far. You will struggle not only with things like setting values for input fields but also emitting HTML5 data-* attributes on your input fields for things like unobtrusive client side validation, all things that are automatically handled by HTML helpers.
You could always perform the following pornography in your view if you find that more readable:
<input type="text" name="Name" value="#Html.Raw(HttpUtility.HtmlAttributeEncode(Model != null ? Model.Name : ""))" />
But I don't know why I kinda prefer writing #Html.TextBoxFor(m => m.Name). I don't know, maybe it's just a matter of personal preference.
But to answer your question, you can do ASP.NET MVC without helpers. It's just that you might find that a pretty disagreeable experience.
I'm just learning how to do ASP MVC. All of the tutorials I see use a combination of Html.LabelFor and the DisplayAttribute. Personally, I'm not a big fan of adding these kinds of annotations to my model objects and I'd like to know if there is an accepted alternative. I thought this might be a place for something like Knockout or Backbone, but I'm so new to this stuff that I'm having difficulty wrapping my brain around the different pieces.
I know this has probably already been asked and answered; I can't even figure out how to google it :(
Thanks in advance
you can skip Data Annotations
you can write
<label for='#(var1)'>#Name</label>
or
<label for='name1'>Text</label>
or
Html.Label("ControlName", "Name")
or
Html.LabelFor with data anot.
any of this will be correct
also using helpers with lamda expressions (Html.LabelFor) is much slower than Html.Label or simple html code <label for='#(var1)'>#Name</label>
It is true for all asp.net mvc html helpers
What is a good approach in ASP.NET MVC for implementing a complex form where sections of the form are shown and hidden based on a user's inputs?
My background is in Webforms. I am frequently asked to build forms where a user selects an option from a dropdown list, triggering a handful of new fields to appear. A different selection might cause a different set of fields to appear.
In the past, I would handle this scenario via an UpdatePanel and a wrapper Panel around the fields that I want to show or hide. Validation is automatically disabled when the fields are hidden.
Going forward, I'd like to make use of MVC's attribute-based model validation, but is it possible to make the validation conditional on the values of other properties?
Also, how can I handle the toggling of blocks of form fields? I know how to do it manually in jQuery, but I'm hoping there's an approach that ties in with validation and server-side code.
I am liking MVC much better overall, but I haven't figured out how to handle this type of scenario very well. Likely I just need to shift my thinking to fit better with the MVC approach.
Josh,
The first thing I's suggest is to make sure you use ViewModels for the pages that are mode complicated. A ViewModel is basically a Model you create for a specific View; for example, a ViewModel could be a composition of other classes.
As for dynamically changing the fields on your View, the best way is to use jQuery (or any other javascript library) to do it.
I also migrated from a web form environment and I know is difficult to change gears at the begining, but trust me, doing a simple jQuery even handler is much simpler than having to put in place a control panel and then the event handlers.
Not to mention that is much more efficient; update panels are after all making partial posts to the page, sometimes, with jQuery you don't even need to do that.
After a few projects with MVC, I actually now find it time consuming to go and do the Update Panels on web forms ;)
Hope this helps,
-Covo
I know this might not be the answer you're looking for, but I personally don't think complex forms are very user friendly in the first place and I always try to split them up into simpler forms where possible, or to simplify the form. I've come across many forms in websites where there are a raft of "fields" where there should really be a few questions for the user to answer. Simple stuff which gets to the point of what they want to achieve rather than the field values, along with a lot of application specific knowledge needed to set those fields to the right values.
If you still want to go ahead with a complex form, then as the other answers have already stated there are facilities provided by MVC to do that, but there isn't any set way. So, it's down to you to figure out what will work best for your users.
Traditional asp.net webforms did alot of "magic" for you whereas you have to be aware of the work that goes into creating the "magic" in asp.net MVC. The benefit is that with MVC you have more control over what is happening which can also enhance performance.
In asp.net webforms an UpdatePanel is used for ajax calls. If you need to got to the server asynchronously(without doing a full post back) then use ajax via JQuery. See below for example:
$.ajax({
type: "get",
url: "/YourController/YourAction",
success: function (obj) {
//any logic you want to do upon success
}
});
The above example will do an ajax HTTP GET call to /YourController/YourAction.
In order to handle "toggling of blocks", if you don't need to go to the server for data and you simply want to do it on the client, then use simple jquery. JQuery has a function for toggling items.
http://api.jquery.com/toggle-event/
Because of the way MVC works in contrast to Webforms you're stuck with the responsibility of really thinking about what happens on the client and what happens on the server separately as not a lot of meta-data is being passed back to give us that happy Webforms feeling.
However, there is a notion when using the built-in AJAX libraries when you render a form that you can have it auto do an update once it is posted. In a sense, it's saving you the JavaScript/JQuery because it "auto-wires" it up similar-ish to a Panel. In this way you could potentially look at progressively rendering your complex forms from the server as each section is edited, etc.
See MSDN: http://msdn.microsoft.com/en-us/library/system.web.mvc.ajax.ajaxoptions.updatetargetid.aspx
The relevant code example to give you an idea (unfortunately, it's not in the more readable Razor syntax):
The relevant line is the Ajax.BeginForm where the form tag is rendered. Once the form is posted, the MS AJAX library will auto update the element specified in "UpdateTargetId" specified in the form's AjaxOptions. In this case, the response will be placed into the SPAN element "textEntered" upon reply from the server. Here, you could progressively render more content to the user to fill out, perhaps another form, etc.
<h2><%= Html.Encode(ViewData["Message"]) %></h2>
<p>
Page Rendered: <%= DateTime.Now.ToLongTimeString() %>
</p>
<span id="status">No Status</span>
<br />
<%= Ajax.ActionLink("Update Status", "GetStatus", new AjaxOptions{UpdateTargetId="status" }) %>
<br /><br />
<% using(Ajax.BeginForm("UpdateForm", new AjaxOptions{UpdateTargetId="textEntered"})) { %>
<%= Html.TextBox("textBox1","Enter text")%>
<input type="submit" value="Submit"/><br />
<span id="textEntered">Nothing Entered</span>
<% } %>
Is there a specific reason why I should be using the Html.CheckBox, Html.TextBox, etc methods instead of just manually writing the HTML?
<%= Html.TextBox("uri") %>
renders the following HTML
<input type="text" value="" name="uri" id="uri"/>
It guess it saves you a few key strokes but other than that. Is there a specific reason why I should go out of my way to use the HtmlHelpers whenever possible or is it just a preference thing?
Another benefit is that if your ViewData contains a value matching the name of the field it will be populated.
e.g.
ViewData["FirstName"] = "Joe Bloggs";
<%=Html.TextBox("FirstName") %>
will render
<input type="text" value="Joe Bloggs" id="FirstName" />
There are huge benefits:
It has overloaded methods to pre-populate the values (formatted, and safe for HTML) just like the ViewState.
It allows built in support for the Validation features of MVC.
It allows you to override the rendering by providing your own DLL for changing the rendering (a sort of "Controller Adapter" type methodology).
It leads to the idea of building your own "controls" : http://www.singingeels.com/Articles/Building_Custom_ASPNET_MVC_Controls.aspx
One thing is for consistency...I for one always forget the name attribute. Plus, you can extend the functions for your own projects. They're not called helpers for nothing!
The upside to using an abstraction layer is future proofing your code in a pluggable way. Maybe today, you create HTML 4 pages but tomorrow you want to create XHTML pages or XAML or XUL. That's a lot of changes if you just hard code the tags everywhere, especially if you've got hundreds of pages. If everything is calling this library, then all you've got to do is rewrite the library. The downside is that it is usually considered to be slightly less readable by humans. So, it most probably increases the cognitive demand on your maintenance programmers. These advantages and disadvantages really have nothing to do with MVC.
It actually auto populates your textbox based upon first your ViewData.Model.uri and second by ViewData["uri"]. Doing it manually you'd need to do <input value="<%Html.Encode(ViewData.Model.Uri"%>" />
I haven't been doing MVC too long, but I've already written some extension methods to generate menu tabs based on Html.ActionLink. It allows me to be consistent with my usage and, if I decide to change how my CSS menus work, only modify a single method to output the new tab format.
The other use that I have made of them is in conditional output using ViewData to supply values to the controls.