5

I'm struggling to display a watermark (so called placeholder) on my MVC3 form inputs.

There is already few posts down here talking including the quite focused one here:

Html5 Placeholders with .NET MVC 3 Razor EditorFor extension?

In these posts, advice is made to create tweaked html.TextBox templates. In my case, my asset is that I should not need any editor template as I'm tweaking them inline.

Better than long talks, here is the relevant part of the actual code:

~/Models/myModel.cs

namespace myProject.Models {
  public class myFormModel {
    ...
    [Display(Name = "firstFieldName", Prompt = "firstFieldPrompt")]
    public string firstFieldValue { get; set; }
    ...
  }
}

~/Controllers/myFormSurfaceController.cs

namespace myProject.Controllers {
  public class myFormSurfaceController : SurfaceController {
    ...
    [ChildActionOnly]
    public PartialViewResult myForm()
    {
        return PartialView("myPartialView", new myFormModel());
    }
    ...
    [HttpPost, ValidateAntiForgeryToken]
    public ActionResult handleMyFormSubmit(myFormModel model) {...}
    ...
  }
}

~/Views/myProject/Partial/myPartialView.cshtml

@model myFormModel
@{      
  using (Html.BeginUmbracoForm("handleMyFormSubmit", "myFormSurface", null, new Dictionary<string, object> { { "class", "myFormStyle" }, { "id", "myFormId" } }))
  {
    ...
    @Html.TextBoxFor(x => x.firstFieldValue, new { @class = "myInputStyle", @placeholder = ViewData.ModelMetadata.Watermark })
    ...
  }
}

Result is that the placeholder html tag is showing up correctly on my rendered webpage but is empty though Name tag is filled up correctly, even without DisplayName decoration set on my view model's property.

http://localhost/testpage

...
<input type="text" value="" placeholder="" name="firstFieldName" id="firstFieldName" class="myInputStyle">
...

What am I missing here ? I did try indeed to create both editor templates (MultilineText and String) in the correct folder (~/Views/Shared/EditorTemplates/) but I assume they are never called as I'm using "Html.TextBoxFor" and not "Html.TextBox"...

Other thing, if I remove "@placeholder = ViewData.ModelMetadata.Watermark" from the @Html.TextBoxFor call, I don't have any "placeholder" displayed on the rendered webpage. Which is good, this part of the call is definitively fine.

Thanks in advance for any help on that point...

Nicolas.

Edit:

What about if I create more variable in my model.

For instance:

public string firstFieldPrompt { get { return "bla"; } set { } } 

and then

@Html.TextBoxFor(x => x.firstFieldValue, new { @class = "myInputStyle", @placeholder = x => x.FirstFieldPrompt })

?

Community
  • 1
  • 1
user1288337
  • 135
  • 1
  • 2
  • 7

2 Answers2

9

I realise this is an oldie, but you can use the ModelMetadata.FromLambdaExpression() method from within your view (without using templates), i.e.

    @Html.TextBoxFor(x => x.firstFieldValue, 
        new { 
            @class = "myInputStyle", 
            @placeholder = ModelMetadata.FromLambdaExpression(x => x.firstFieldValue, ViewData).Watermark 
    })

Hope this helps someone :-)

Kristine
  • 91
  • 1
  • 2
  • 1
    It has been available since MVC 2 (http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html and http://stackoverflow.com/questions/6443565/asp-net-mvc-2-getting-modelmetadata-from-a-view-without-a-custom-template) – Kristine May 25 '14 at 11:42
7

The reason you get an empty watermark is that in your case (i.e. not using templates) ViewData actually refers to myFormModel (not myFormModel.firstFieldValue); you are essentially retrieving the watermark of your view model. Since models can't have watermarks ([Display] can't be applied to classes) ViewData.ModelMetadata.Watermark will always be empty for views.

As far as I can see, your only option here (if you don't want to use templates) is doing the watermark inline:

@Html.TextBoxFor(x => x.firstFieldValue, new { @class = "myInputStyle", placeholder = "Your watermark text here" })

By the way, if want to use templates, you need to use the templated helpers @Html.EditorFor() and @Html.DisplayFor(). @Html.TextBoxFor() is just the strongly-typed version of @Html.TextBox(). It is not templated.

Daniel Liuzzi
  • 16,807
  • 8
  • 52
  • 57
  • No problem. I'm not sure what you are trying to do in your last example. `Placeholder` is just a string. Passing a lambda like you are doing is not going to work. And even if it did, why would you want to use the property's value as a watermark? That's what the value attribute is for. If all you want to do is having flexibility with the watermark, the template approach is the most elegant and straightforward one IMO. Is there any particular reason you don't want to go that route? – Daniel Liuzzi Mar 26 '12 at 14:01
  • 1
    can't believe this is still happening on MVC4 ... EditorFor lacks htmlAttributes and TextBoxFor lacks placeholders .... – Bart Calixto Aug 20 '13 at 00:20