EditorFor () dan properti html


113

Versi pratinjau Asp.Net MVC 2.0 menyediakan pembantu seperti

Html.EditorFor(c => c.propertyname)

Jika nama properti adalah string, kode di atas membuat texbox.

Bagaimana jika saya ingin meneruskan properti MaxLength dan Size ke kotak teks atau properti kelas css saya sendiri?

Apakah saya perlu membuat satu template untuk setiap kombinasi ukuran dan panjang dalam aplikasi saya? Jika demikian, itu tidak membuat templat default dapat digunakan.

Jawaban:


92

Di MVC3, Anda dapat mengatur lebar sebagai berikut:

@Html.TextBoxFor(c => c.PropertyName, new { style = "width: 500px;" })

62
@tokopedia Pastikan ini TEXTBOX dan bukan EDITOR. Doenst bekerja dengan editor.
Kasper Skov

1
Ia juga bekerja dengan textareas: @ Html.TextAreaFor (c => c.PropertyName, new {style = "width: 500px;"})
Tarzan

Perhatikan bahwa beberapa penjelasan data yang tidak didukung oleh TextBoxFor, yang akan bekerja dengan EditorFor, seperti formatstring
AaronLS

14
Bukankah jawaban ini, benar-benar mengabaikan pertanyaannya, yaitu fungsi EditorFor-Template?
Philipp M

1
Namun menggunakan TextBoxFor mematikan format tampilan yang ditetapkan sebagai anotasi data
Anders Lindén

61

Saya menyelesaikan ini dengan membuat EditorTemplate bernama String.ascx di folder / Views / Shared / EditorTemplates saya:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>
<% int size = 10;
   int maxLength = 100;
   if (ViewData["size"] != null)
   {
       size = (int)ViewData["size"];
   }
   if (ViewData["maxLength"] != null)
   {
       maxLength = (int)ViewData["maxLength"];
   }
%>
<%= Html.TextBox("", Model, new { Size=size, MaxLength=maxLength }) %>

Dalam pandangan saya, saya menggunakan

<%= Html.EditorFor(model => model.SomeStringToBeEdited, new { size = 15, maxLength = 10 }) %>

Bekerja seperti pesona bagi saya!


1
brilian - Saya memiliki drop-down DateTime pemilih data yang sudah saya buat template, tetapi memberikan atribut tambahan padanya terbukti menyakitkan - ini menyelesaikannya untuk saya, terima kasih!
Terry_Brown

EditorFor dengan maxlength tidak berfungsi untuk saya (TextBoxFor di sisi lain
berfungsi

@tjeerdhans, saya menggunakan kode ini untuk menyesuaikan css saya. Ini berfungsi tetapi sayangnya itu menggantikan nilai css asli. Bagaimana cara membuatnya ditambahkan ke css asli?
Rosdi Kasim

33

Tidak ada jawaban di utas ini atau lainnya tentang menyetel atribut HTML untuk @ Html.EditorFor yang sangat membantu saya. Namun, saya menemukan jawaban yang bagus di

Styling helper @ Html.EditorFor

Saya menggunakan pendekatan yang sama dan itu bekerja dengan baik tanpa menulis banyak kode tambahan. Perhatikan bahwa atribut id dari keluaran html dari Html.EditorFor disetel. Kode tampilan

<style type="text/css">
#dob
{
   width:6em;
}
</style>

@using (Html.BeginForm())
{
   Enter date: 
   @Html.EditorFor(m => m.DateOfBirth, null, "dob", null)
}

Properti model dengan anotasi data dan format tanggal sebagai "dd MMM yyyy"

[Required(ErrorMessage= "Date of birth is required")]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd MMM yyyy}")]
public DateTime DateOfBirth { get; set; }

Bekerja seperti pesona tanpa menulis banyak kode tambahan. Jawaban ini menggunakan ASP.NET MVC 3 Razor C #.


1
Bekerja dengan sangat baik untuk saya juga di MVC4.
atconway

1
Pemformatan berfungsi tetapi sekarang null dikembalikan untuk data yang secara efektif menonaktifkan kotak.
Joe

2
Saya tidak tahu apa itu MVC, sepertinya tidak ada yang menulis situs web yang bekerja dengan berbagai bahasa dan format angka.
adudley

Baik sekali. Ini sederhana, berhasil, dan sebenarnya menjawab pertanyaan OP, alih-alih memberikan alternatif. Menggunakan MVC4.
draconis

Peringatan: DateTimes tampak dirender sebagai type = "datetime", yang salah untuk tanggal lahir, dan beberapa browser (seperti Firefox seluler) sebenarnya mendukung dengan benar jenis masukan tersebut, termasuk komponen waktu yang mungkin tidak lolos validasi dan sulit atau mustahil bagi pengguna untuk menghapusnya.
Brianary

25

Mungkin ingin melihat postingan Blog Kiran Chand , dia menggunakan metadata khusus pada model tampilan seperti:

[HtmlProperties(Size = 5, MaxLength = 10)]
public string Title { get; set; }

Ini digabungkan dengan template khusus yang menggunakan metadata. Pendekatan yang bersih dan sederhana menurut saya, tetapi saya ingin melihat kasus penggunaan umum ini ada di dalam mvc.


71
Apa Anda sedang bercanda? Ini terlalu berlebihan untuk hal sesederhana itu. Semakin banyak saya akan kembali ke HTML murni dan melupakan metode pembantu MVC yang membengkak. 5 menit yang lalu saya memiliki TextboxFor sederhana yang berhasil meluncurkan jquery datepicker. Sekarang hanya karena saya ingin mengubah cara memformat nilai tanggal yang dimuat sebelumnya, saya harus mengubahnya menjadi EditorFor. Tetapi sekarang tiba-tiba saya tidak dapat menentukan atribut HTML saya sendiri tanpa menulis metode dan bantuan ekstensi khusus yang terlalu membengkak ini. Lelucon apa. Pasti ada cara yang lebih sederhana, Anda para profesor gila tidak tahu kapan harus berhenti.
Aaron

1
Saya pikir Anda mencampurkan konteks. Bagaimana Anda bisa memiliki dua panggilan EditorFor yang berbeda dengan masing-masing mendapatkan ukuran dan nilai panjang maksimumnya sendiri dengan tautan yang Anda berikan? Jika Anda tidak ingin menggunakan EditorFor, Anda selalu dapat menggunakan pembantu TextBox atau html sederhana. Tapi bukan itu pertanyaannya!
chandmk

@Aaron pada MVC terbaru, Anda dapat menentukan atribut html tambahan dengan EditorFormeneruskannya sebagai:new { htmlAttributes: { @class = "yourclass" } }
JoeBrockhaus

17

Saya terkejut tidak ada yang menyebutkan menyampaikannya di "additionalViewData" dan membacanya di sisi lain.

Lihat (dengan jeda baris, untuk kejelasan):

<%= Html.EditorFor(c => c.propertyname, new
    {
        htmlAttributes = new
        {
            @class = "myClass"
        }
    }
)%>

Template editor:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<string>" %>

<%= Html.TextBox("", Model, ViewData["htmlAttributes"])) %>

Membangun ini saya membuat pembantu yang memperhitungkan penggabungan atribut - stackoverflow.com/a/11498094/79842
Colin Bowern

6

Masalahnya adalah, template Anda bisa berisi beberapa elemen HTML, jadi MVC tidak akan tahu mana yang akan menerapkan ukuran / kelas Anda. Anda harus mendefinisikannya sendiri.

Buat template Anda berasal dari kelas Anda sendiri yang disebut TextBoxViewModel:

public class TextBoxViewModel
{
  public string Value { get; set; }
  IDictionary<string, object> moreAttributes;
  public TextBoxViewModel(string value, IDictionary<string, object> moreAttributes)
  {
    // set class properties here
  }
  public string GetAttributesString()
  {
     return string.Join(" ", moreAttributes.Select(x => x.Key + "='" + x.Value + "'").ToArray()); // don't forget to encode
  }

}

Di template Anda dapat melakukan ini:

<input value="<%= Model.Value %>" <%= Model.GetAttributesString() %> />

Dalam pandangan Anda, Anda melakukan:

<%= Html.EditorFor(x => x.StringValue) %>
or
<%= Html.EditorFor(x => new TextBoxViewModel(x.StringValue, new IDictionary<string, object> { {'class', 'myclass'}, {'size', 15}}) %>

Formulir pertama akan membuat template default untuk string. Formulir kedua akan membuat template kustom.

Sintaks alternatif menggunakan antarmuka yang lancar:

public class TextBoxViewModel
{
  public string Value { get; set; }
  IDictionary<string, object> moreAttributes;
  public TextBoxViewModel(string value, IDictionary<string, object> moreAttributes)
  {
    // set class properties here
    moreAttributes = new Dictionary<string, object>();
  }

  public TextBoxViewModel Attr(string name, object value)
  {
     moreAttributes[name] = value;
     return this;
  }

}

   // and in the view
   <%= Html.EditorFor(x => new TextBoxViewModel(x.StringValue).Attr("class", "myclass").Attr("size", 15) %>

Perhatikan bahwa alih-alih melakukan ini dalam tampilan, Anda juga dapat melakukan ini di pengontrol, atau jauh lebih baik di ViewModel:

public ActionResult Action()
{
  // now you can Html.EditorFor(x => x.StringValue) and it will pick attributes
  return View(new { StringValue = new TextBoxViewModel(x.StringValue).Attr("class", "myclass").Attr("size", 15) });
}

Juga perhatikan bahwa Anda dapat membuat kelas TemplateViewModel dasar - dasar yang sama untuk semua templat tampilan Anda - yang akan berisi dukungan dasar untuk atribut / dll.

Tapi secara umum saya rasa MVC v2 membutuhkan solusi yang lebih baik. Ini masih Beta - tanyakan saja ;-)


Saya pikir cara yang lebih baik untuk menangani ini adalah seperti yang saya sebutkan di sini stackoverflow.com/questions/1647609/… ... Singkatnya melakukan sesuatu yang mirip dengan cara WPF menangani masalah ... Elemen gaya sewenang-wenang (dalam kasus ini) atribut) diteruskan ke template dan template memutuskan elemen internal mana yang akan menerapkan gayanya ...
vdhant

6

Saya pikir menggunakan CSS adalah cara terbaik. Saya berharap saya bisa berbuat lebih banyak dengan pengkodean .NET, seperti di XAML, tetapi di browser CSS adalah rajanya.

Site.css

#account-note-input { 
  width:1000px; 
  height:100px; 
} 

.cshtml

<div class="editor-label"> 
  @Html.LabelFor(model => model.Note) 
</div> 
<div class="editor-field"> 
  @Html.EditorFor(model => model.Note, null, "account-note-input", null) 
  @Html.ValidationMessageFor(model => model.Note) 
</div>

Joe


Ini bekerja sangat baik untuk membuat perubahan CSS khusus kontrol saat menggunakan EditorFortemplate. Saya menggunakan MVC4 dan ini bekerja dengan baik.
atconway

6

Seperti di MVC 5, jika Anda ingin menambahkan atribut apa pun, Anda dapat melakukannya

 @Html.EditorFor(m => m.Name, new { htmlAttributes = new { @required = "true", @anotherAttribute = "whatever" } })

Informasi ditemukan dari blog ini


3

Anda dapat menentukan atribut untuk properti Anda.

[StringLength(100)]
public string Body { get; set; }

Ini dikenal sebagai System.ComponentModel.DataAnnotations. Jika Anda tidak dapat menemukan ValidationAttributeyang Anda butuhkan, Anda selalu dapat menentukan atribut khusus.

Salam Hormat, Carlos


3
Dia berbicara tentang atribut Html seperti maxlength bukan validasi.
Mathias F

Saya berharap mesin tampilan akan mematuhi DataAnnotations juga. Saya belum main-main dengan MVC2.
mxmissile

Saya mencoba anotasi data StringLength. Itu tidak bekerja dengan EditorFor.
wayne.blackmon

3

Ini mungkin bukan solusi paling licin, tetapi langsung saja. Anda dapat menulis ekstensi ke kelas HtmlHelper.EditorFor. Dalam ekstensi itu, Anda dapat menyediakan parameter opsi yang akan menulis opsi ke ViewData untuk helper. Berikut beberapa kode:

Pertama, metode ekstensi:

public static MvcHtmlString EditorFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, TemplateOptions options)
{
    return helper.EditorFor(expression, options.TemplateName, new
    {
        cssClass = options.CssClass
    });
}

Selanjutnya, objek opsi:

public class TemplateOptions
{
    public string TemplateName { get; set; }
    public string CssClass { get; set; }
    // other properties for info you'd like to pass to your templates,
    // and by using an options object, you avoid method overload bloat.
}

Dan terakhir, inilah baris dari template String.ascx:

<%= Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = ViewData["cssClass"] ?? "" }) %>

Sejujurnya, saya pikir ini mudah dan jelas bagi jiwa malang yang harus menjaga kode Anda di jalan. Dan mudah untuk memperluas berbagai bit info lain yang ingin Anda teruskan ke template Anda. Ini bekerja dengan baik sejauh ini untuk saya dalam sebuah proyek di mana saya mencoba untuk membungkus sebanyak yang saya bisa dalam satu set template untuk membantu menstandarkan html sekitarnya, a la http://bradwilson.typepad.com/blog/2009/ 10 / aspnet-mvc-2-templates-part-5-master-page-templates.html .


3

Saya menulis entri blog untuk menjawab pertanyaan saya sendiri

Menambahkan dukungan atribut html untuk Template - ASP.Net MVC 2.0 Beta


Ide menempatkan properti pemformatan HTML pada model (view) bertentangan dengan ide MVC untuk memisahkan tampilan dan logika! Bagaimana jika model membutuhkan representasi yang berbeda dalam HTML?
saintedlama

2
@Saintedlama: Tidak masalah untuk meletakkan anotasi data pada viewmodel , karena tujuan satu-satunya viewmodel adalah menyediakan model data terstruktur untuk tampilan tersebut . Jangan bingung dengan model , yang dalam terminologi MVC biasanya mewakili entitas DB, yang seharusnya tidak memiliki properti terkait tampilan. Karena itu, sangat disayangkan anotasi viewmodelnya dimulai dengan HTMLxxx karena itu menyiratkan HTML sebagai lapisan presentasi, tetapi garis harus ditarik di suatu tempat. :) Selain itu, jika dia menggunakan kembali viewmodel untuk katakanlah aplikasi silverlight, dia dapat dengan mudah menambahkan atribut SL ke viewmodelnya.
Boris B.

3

Saya tidak tahu mengapa itu tidak berfungsi untuk Html.EditorFor tetapi saya mencoba TextBoxFor dan itu berhasil untuk saya.

@Html.TextBoxFor(m => m.Name, new { Class = "className", Size = "40"})

... dan juga validasi bekerja.


Anda perlu@class = "className"
JoeBrockhaus

2

Dalam praktik saya, saya menemukan bahwa yang terbaik adalah menggunakan EditorTemplates hanya dengan satu HtmlHelper di dalamnya - TextBox yang dalam banyak kasus. Jika saya menginginkan template untuk struktur html yang lebih kompleks, saya akan menulis HtmlHelper terpisah.

Mengingat bahwa kita bisa menempelkan seluruh objek ViewData di tempat htmlAttributes dari TextBox. Selain itu, kami dapat menulis beberapa kode penyesuaian untuk beberapa properti ViewData jika mereka memerlukan perlakuan khusus:

@model DateTime?
@*
    1) applies class datepicker to the input;
    2) applies additionalViewData object to the attributes of the input
    3) applies property "format" to the format of the input date.
*@
@{
    if (ViewData["class"] != null) { ViewData["class"] += " datepicker"; }
    else { ViewData["class"] = " datepicker"; }
    string format = "MM/dd/yyyy";
    if (ViewData["format"] != null)
    {
        format = ViewData["format"].ToString();
        ViewData.Remove("format");
    }
}

@Html.TextBox("", (Model.HasValue ? Model.Value.ToString(format) : string.Empty), ViewData)

Di bawah ini adalah contoh sintaks dalam tampilan dan html yang dikeluarkan:

@Html.EditorFor(m => m.Date)
<input class="datepicker" data-val="true" data-val-required="&amp;#39;Date&amp;#39; must not be empty." id="Date" name="Date" type="text" value="01/08/2012">
@Html.EditorFor(m => m.Date, new { @class = "myClass", @format = "M/dd" })
<input class="myClass datepicker" data-val="true" data-val-required="&amp;#39;Date&amp;#39; must not be empty." id="Date" name="Date" type="text" value="1/08">

2

Karena pertanyaannya adalah untuk EditorFor, bukan TextBoxFor, saran WEFX tidak berfungsi.

Untuk mengubah kotak masukan individual, Anda dapat memproses keluaran metode EditorFor:

<%: new HtmlString(Html.EditorFor(m=>m.propertyname).ToString().Replace("class=\"text-box single-line\"", "class=\"text-box single-line my500pxWideClass\"")) %>

Dimungkinkan juga untuk mengubah SEMUA EditorFors Anda karena ternyata MVC menetapkan kelas kotak teks EditorFor dengan .text-box , oleh karena itu Anda dapat mengganti gaya ini, di lembar gaya atau di halaman.

.text-box {
    width: 80em;
}

Selain itu, Anda dapat mengatur gayanya

input[type="text"] {
    width: 200px;
}
  • ini menggantikan .text-box dan akan mengubah semua kotak teks masukan, EditorFor atau sebaliknya.

Tidak semua kotak teks EditorFor () adalah input type = "text". Properti DateTime tampaknya dirender sebagai type = "datetime".
Brianary

2

Saya juga memiliki masalah dengan pengaturan lebar TextBox di MVC3, sementara pengaturan atribut Clsss berfungsi untuk kontrol TextArea tetapi tidak untuk kontrol TextBoxFor atau kontrol EditorFor:

Saya mencoba mengikuti & itu berhasil untuk saya:

@ Html.TextBoxFor (model => model.Title, baru {Class = "textBox", style = "width: 90%;"})

juga dalam hal ini Validasi bekerja dengan sempurna.


2

Salah satu cara Anda bisa mengatasinya adalah dengan memiliki delegasi pada model tampilan untuk menangani pencetakan rendering khusus seperti ini. Saya telah melakukan ini untuk kelas paging, saya mengekspos properti publik pada modelFunc<int, string> RenderUrl untuk menghadapinya.

Jadi tentukan bagaimana bit kustom akan ditulis:

Model.Paging.RenderUrl = (page) => { return string.Concat(@"/foo/", page); };

Keluarkan tampilan untuk Pagingkelas:

@Html.DisplayFor(m => m.Paging)

... dan untuk tampilan sebenarnya Paging:

@model Paging
@if (Model.Pages > 1)
{
    <ul class="paging">
    @for (int page = 1; page <= Model.Pages; page++)
    {
        <li><a href="@Model.RenderUrl(page)">@page</a></li>
    }
    </ul>
}

Ini bisa dilihat sebagai masalah yang terlalu rumit tetapi saya menggunakan pager ini di mana-mana dan tidak tahan melihat kode boilerplate yang sama untuk membuatnya ditampilkan.


1

UPDATE: hm, jelas ini tidak akan berfungsi karena model dilewatkan oleh nilai sehingga atribut tidak dipertahankan; tapi saya tinggalkan jawaban ini sebagai ide.

Solusi lain, menurut saya, adalah menambahkan pembantu TextBox / etc Anda sendiri, yang akan memeriksa atribut Anda sendiri pada model.

public class ViewModel
{
  [MyAddAttribute("class", "myclass")]
  public string StringValue { get; set; }
}

public class MyExtensions
{
  public static IDictionary<string, object> GetMyAttributes(object model)
  {
     // kind of prototype code...
     return model.GetType().GetCustomAttributes(typeof(MyAddAttribute)).OfType<MyAddAttribute>().ToDictionary(
          x => x.Name, x => x.Value);
  }
}

<!-- in the template -->
<%= Html.TextBox("Name", Model, MyExtensions.GetMyAttributes(Model)) %>

Yang ini lebih mudah tetapi tidak begitu nyaman / fleksibel.



0

Saya sangat menyukai jawaban @tjeerdans yang menggunakan EditorTemplate bernama String.ascx di folder / Views / Shared / EditorTemplates. Sepertinya ini adalah jawaban paling langsung untuk pertanyaan ini. Namun, saya ingin template menggunakan sintaks Razor. Selain itu, tampaknya MVC3 menggunakan template String sebagai default (lihat pertanyaan StackOverflow " template tampilan mvc untuk string digunakan untuk bilangan bulat ") sehingga Anda perlu menyetel model ke objek daripada string. Template saya sepertinya berfungsi sejauh ini:

@model object 

@{  int size = 10; int maxLength = 100; }

@if (ViewData["size"] != null) {
    Int32.TryParse((string)ViewData["size"], out size); 
} 

@if (ViewData["maxLength"] != null) {
    Int32.TryParse((string)ViewData["maxLength"], out maxLength); 
}

@Html.TextBox("", Model, new { Size = size, MaxLength = maxLength})

0

Saya menyelesaikannya !!
Untuk Razor sintaksnya adalah:
@Html.TextAreaFor(m=>m.Address, new { style="Width:174px" })ini menyesuaikan lebar area teks dengan lebar yang saya tentukan dalam parameter gaya.
Untuk ASPx sintaksnya adalah:
<%=Html.TextAreaFor(m => m.Description, new { cols = "20", rows = "15", style="Width:174px" })%>
ini akan melakukan trik

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.