I may be off my rocker, but since HTML5 came out, does Microsoft have a namespace similar to
using System.Web.Mvc.Html
for HTML5 helpers in your MVC views?
I can't believe they don't have something out for this.... I'm using Visual Studio 13 Update 3.
If they don't, can you simply apply HTML5 tags for the specific model you're using with the View?
So, for example, if you just have an HTML5 input tag as text, can you say something like:
#using exampleModel
#exampleModel.Name
If you say:
#Html.EditorFor(m => m.Name)
... the default editor templates in the latest versions of MVC will render input tags that correspond to the type you provide. For example, if the property is a number you'll get <input type="number"...>.
Related
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.
I've found myself working on a .Net MVC3 project and sorely missing having Formtastic available in my rails apps.
Are there any good .Net MVC replacements for Formtastic?
I suggest using MVC3s HTML Helpers.
#model mynspace.MyModel
#Html.EditorForModel()
This html helper generates editor fields for every field in your model, choosing the most likely option. Editing the Editor template, you can change the way it is layed out as well. See this question on changing the template
It can of course be used more customizable by each field with things like:
#Html.Label("Daily Rate")
#Html.EditorFor(model => model.DailyRate)
#Html.ValidationMessageFor(model => model.DailyRate, "Please enter a valid Daily Rate (2 d.p.)")
This can be custom layed out by putting tags around it, i.e. things like <p> or <td>
You can also force an input type using options like:
#Html.TextBoxFor(model => model.DailyRate)
#Html.CheckBoxFor(model => model.DailyRate)
#Html.DropDownBoxFor(model => model.DailyRate, ViewBag.DailyRates)
see here for a full list of options
I have a project called FormFactory that lets you do much of the stuff formastic does http://formfactory.apphb.com/
It transforms model objects into PropertyVm objects, which are a viewmodel for an input basically. You could manually create the PropertyVms if you want.
I have following code
#Html.Pager((IPagination)Model.FoundUsers).Last("<span class=\"last\"> </span>").First("<span class=\"first\"> </span>").Next("<span class=\"next\"> </span>").Previous("<span class=\"prev\"> </span>")
But it renders encoded and shows <span class="next"> on page.
I tried to used Html.Raw as suggested in Problem with razor view and mvccontrib grid pagination or How to make a pager with MVCContrib and Razor?
but it still does not work for me.
What am I doing wrong ?
I would assume that you are using MvcContrib v2 with Mvc4 (or possibly Mvc3)?
Either manually download the newer libraries from http://mvccontrib.codeplex.com or use the Raw method. So instead of this:
#Html.Pager((IPagination)Model.FoundUsers).Last("<span class=\"last\"> </span>").First("<span class=\"first\"> </span>").Next("<span class=\"next\"> </span>").Previous("<span class=\"prev\"> </span>")
You would instead have:
#Html.Raw(Html.Pager((IPagination)Model.FoundUsers).Last("<span class=\"last\"> </span>").First("<span class=\"first\"> </span>").Next("<span class=\"next\"> </span>").Previous("<span class=\"prev\"> </span>"))
Perhaps it's because I am working in VB, but I had to get the appropriate string from the Pager object:
#Html.Raw(Html.Pager(Model).ToString)
I'm using MvcContrib 2.0.95 with MVC 3.
When I add a new strongly-typed view in VStudio 2010, I get fields layed out like this.
<div class="display-label">Id</div>
<div class="display-field"><%= Html.Encode(Model.Id) %></div>
In 2008, it used to use p tags instead of all these divs, my css is set up to handle the p tags properly, but since upgrading I have these now, so I have to spend time editing by hand removing the divs and adding p tags. (Plus, I just like the idea of using logical p tags instead of this mess.)
Is there a way I can modify the template?
Yes, you can. This if for MVC3 but I believe it is very similar if not the same for MVC2.
You can also override the templates by creating your own display templates. Brad Wilson shows this... and one more....
What I mean by that is a type element that will have a label based on a value in my viewModel and also be able to submit that value back up to the viewModel so it can grab new results based on Current Page and Page Size. This is for creating a gridview in MVC that supports pagination.
None of the examples I've seen of MVC so far have had anything resembling a gridview. It's important that I create my own paging and not use any built in paging mechanisms or third party controls or html helpers or the like
I'd go with ActionLink. To build Urls you can either use Url.Action or Html.BuildUrlFromExpression(c => c.conTrollerAction)
If you use T4MVC, you will get some nice helpers that do exactly what you are looking for.
Something along the lines of:
<a href="<%: Url.Action(MVC.MyController.MyAction(Model.ActionMethodParam1, Model.ActionMethodParam2)) %>">
You can also use the Html.ActionLink helper:
<%: Html.ActionLink("Link Name", MVC.MyController.MyAction(Model.ActionMethodParam1, Model.ActionMethodParam2)) %>
T4MVC is a great little library that I use in every MVC app.