ASP.NET MVC 3 Razor - Thêm lớp vào EditorFor


189

Tôi đang cố gắng thêm một lớp vào một đầu vào.

Đây không phải là làm việc:

@Html.EditorFor(x => x.Created, new { @class = "date" })

1
hey bạn thậm chí có tên đúng quá! - (đối với mã của tôi)
Pinch

1
LƯU Ý: Đối với một số câu trả lời, ngay cả khi chúng là chính xác, người ta có thể phải xóa bộ đệm của trình duyệt để nó được hiện thực hóa. Điều này đặc biệt đúng nếu giải pháp dựa trên css hoặc liên quan đến lớp css! Chỉ mất một lúc để nhận ra rằng với một vấn đề hơi khác ....
JosephDoggie

Câu trả lời:


183

Thêm một lớp để Html.EditorForkhông có ý nghĩa như trong mẫu của nó, bạn có thể có nhiều thẻ khác nhau. Vì vậy, bạn cần chỉ định lớp bên trong mẫu trình soạn thảo:

@Html.EditorFor(x => x.Created)

và trong mẫu tùy chỉnh:

<div>
    @Html.TextBoxForModel(x => x.Created, new { @class = "date" })
</div>

5
Điều này làm việc tuyệt vời, cảm ơn. Gặp sự cố định dạng giá trị trường theo chú thích DisplayFormat trong mô hình của tôi. Được định dạng như chú thích với EditorFor và DisplayFor, nhưng không phải là TextBoxFor :( Hình như tôi phải sử dụng một mẫu tùy chỉnh, trừ khi ai đó có thể chỉ cho tôi thứ gì đó tôi đang thiếu.?
Sean

Có cùng một vấn đề trong đó TextBoxFor không tôn trọng bộ DisplayFormat.
vui vẻ

14
Đây là GroundControll đến ModelTom, tôi đang gửi cho bạn Chế độ xem và tôi đang nổi theo cách MVC nhất.
Trent Stewart

3
Tôi có cùng một vấn đề, nhưng tôi không thể sử dụng TextBoxFor vì tôi cần DisplayFormat, hoạt động với Trình chỉnh sửa hoặc Hiển thị, nhưng đồng thời tôi cũng cần lớp, để tôi có thể hiển thị văn bản ở dạng chỉ đọc
AT

153

Kể từ ASP.NET MVC 5.1, việc thêm một lớp vào một EditorForlà có thể (câu hỏi ban đầu chỉ định ASP.NET MVC 3, và câu trả lời được chấp nhận vẫn là tốt nhất với câu hỏi được xem xét).

@Html.EditorFor(x=> x.MyProperty,
    new { htmlAttributes = new { @class = "MyCssClass" } })

Xem: Có gì mới trong ASP.NET MVC 5.1, hỗ trợ Bootstrap cho các mẫu biên tập


Thật tuyệt vời. Cảm ơn!
Neill

1
Tôi gần như đã bỏ lỡ điều này vì nó đứng thứ 3 trong danh sách. Có lẽ sẽ hữu ích khi đặt câu hỏi của riêng nó và sau đó tự trả lời.
Robb Sadler

Trong MVC 2,3,4 tôi không có ý nghĩa gì ... nhưng khi nhiều người bắt đầu sử dụng và phàn nàn về việc thiếu nó - Nó đột nhiên có ý nghĩa trong MVC 5: D +1
Piotr Kula

Điều này bây giờ nên là câu trả lời được chấp nhận theo ý kiến ​​của tôi.
Manfred

101

Bạn không thể thiết lập lớp cho EditorFor chung. Nếu bạn biết trình soạn thảo mà bạn muốn, bạn có thể sử dụng nó ngay lập tức, ở đó bạn có thể thiết lập lớp. Bạn không cần phải xây dựng bất kỳ mẫu tùy chỉnh nào.

@Html.TextBoxFor(x => x.Created, new { @class = "date" }) 

5
Thỏa thuận tốt, thật tuyệt khi không cần phải xây dựng một mẫu tùy chỉnh.
Steve Duitsman

bạn đã tiết kiệm rất nhiều thời gian cho tôi jo!
Prashanth Benny

39

Bạn có thể dùng:

@Html.EditorFor(x => x.Created, new { htmlAttributes = new { @class = "date" } })

(Ít nhất là với ASP.NET MVC 5, nhưng tôi không biết điều đó như thế nào với ASP.NET MVC 3.)


Vui lòng đọc tiêu đề câu hỏi, đây là vấn đề của MVC3, bạn cung cấp giải pháp MVC5 hoàn toàn sai lệch.
Vincent

10
Và bạn vui lòng đọc toàn bộ bài viết của tôi, nơi tôi đã viết nó cho MVC5. Đây là kết quả đầu tiên từ Google, vì vậy sau khi tôi tìm thấy giải pháp tôi muốn, hãy chia sẻ nó ở đây, có lẽ nó có thể giúp một số người.
przno

Cái này giúp tôi với! Cảm ơn @przno
Joakim M

29

Tôi cũng gặp vấn đề khó chịu tương tự và tôi không muốn tạo Trình soạn thảo áp dụng cho tất cả các giá trị DateTime (có những lúc trong UI của tôi nơi tôi muốn hiển thị thời gian và không phải lịch thả xuống UI UI ). Trong nghiên cứu của tôi, các vấn đề gốc tôi gặp phải là:

  • Chuẩn mực trợ giúp TextBoxFor cho phép tôi áp dụng một lớp "trình chọn ngày" tùy chỉnh để hiển thị lịch trình UI UI không phô trương, nhưng TextBoxFor sẽ không định dạng DateTime mà không có thời gian, do đó khiến kết xuất lịch không thành công.
  • Trình soạn thảo chuẩn sẽ hiển thị DateTime dưới dạng một chuỗi được định dạng (khi được trang trí với các thuộc tính phù hợp như [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")], nhưng nó sẽ không cho phép tôi áp dụng lớp "chọn ngày" tùy chỉnh.

Do đó, tôi đã tạo lớp HtmlHelper tùy chỉnh có các lợi ích sau:

  • Phương thức tự động chuyển đổi DateTime thành ShortDateString cần theo lịch jQuery (jQuery sẽ thất bại nếu có thời gian).
  • Theo mặc định, trình trợ giúp sẽ áp dụng các htmlAttribution cần thiết để hiển thị lịch jQuery, nhưng chúng có thể bị ghi đè nếu cần.
  • Nếu ngày là null, ASP.NET MVC sẽ đặt ngày là 1/1/0001 làm giá trị.

Phương pháp này thay thế bằng một chuỗi rỗng.

public static MvcHtmlString CalenderTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null)
{
    var mvcHtmlString = System.Web.Mvc.Html.InputExtensions.TextBoxFor(htmlHelper, expression, htmlAttributes ?? new { @class = "text-box single-line date-picker" });
    var xDoc = XDocument.Parse(mvcHtmlString.ToHtmlString());
    var xElement = xDoc.Element("input");
    if (xElement != null)
    {
        var valueAttribute = xElement.Attribute("value");
        if (valueAttribute != null)
        {
            valueAttribute.Value = DateTime.Parse(valueAttribute.Value).ToShortDateString();
            if (valueAttribute.Value == "1/1/0001")
                valueAttribute.Value = string.Empty;
        }
    }
    return new MvcHtmlString(xDoc.ToString());
}

Và đối với những người muốn biết cú pháp JQuery tìm kiếm các đối tượng có date-pickertrang trí lớp để hiển thị lịch, thì đây là:

$(document).ready(function () {
    $('.date-picker').datepicker({ inline: true, maxDate: 0, changeMonth: true, changeYear: true });
    $('.date-picker').datepicker('option', 'showAnim', 'slideDown');
});

Điều đó đã giúp tôi ngay bây giờ, một vấn đề nhỏ với nó - bạn cần kiểm tra để đảm bảo giá trịAttribution.Value không trống hoặc khoảng trắng trước khi chuyển nó sang phương thức DateTime.Pude, nếu không, bạn có nguy cơ bị FormatException ném vào trường trống.
Moo

Cảm ơn. Bạn đã giúp tôi nhiều.
Bronzato

Điều này đã giúp tôi, tuy nhiên nếu bạn đang thực hiện điều này và bạn đang mong đợi trường thực hiện xác thực, bạn sẽ cần áp dụng logic này: stackoverflow.com/questions/12023970/ trộm
Aaron Newton

Tốt lắm, nhưng bạn có biết bạn có thể kiểm soát nếu DateTime hoặc chỉ một điều khiển Ngày xuất hiện chỉ bằng cách sử dụng DateTimePickerForvà cập nhật trường ngày của mô hình mà bạn đại diện với [DataType(DataType.Date)]hoặc [DataType(DataType.DateTime)]? Bạn cũng có thể đặt nó vào dạng giả sử mm / dd / yyyy với .ParseFormats(new string[] { "MM/dd/yyyy" })(hoặc sửa đổi nó thành bất cứ điều gì bạn muốn, một cách dễ dàng). Nếu không có giá trị, trường sẽ hiển thị trống mà không phải mã hóa.
vapcguy

Dao cạo sẽ không nhận ra @MyHtmlHelpers.CalenderTextBoxFor(model => model.ExpirationDate). Bất kỳ ý tưởng về cách thực hiện điều này?
Mehdiway

15

Có thể cung cấp một lớp hoặc thông tin khác thông qua ExtraViewData - Tôi sử dụng điều này khi tôi cho phép người dùng tạo biểu mẫu dựa trên các trường cơ sở dữ liệu (propertyName, EditorType và EditorClass).

Dựa trên ví dụ ban đầu của bạn:

@Html.EditorFor(x => x.Created, new { cssClass = "date" })

và trong mẫu tùy chỉnh:

<div>
    @Html.TextBoxFor(x => x.Created, new { @class = ViewData["cssClass"] })
</div>

8
@ Html.EditorFor (x => x.Created, {cssClass = "date"}) mới không hoạt động với tôi
Alan Macdonald

1
Điều này làm việc cho tôi và là một câu trả lời tốt hơn so với câu trả lời. Nó cung cấp lợi ích của việc sử dụng một mẫu, nhưng vẫn cho phép một số tùy chỉnh mà không cần hack jQuery.
Chad Hedgcock

TextBoxFor bỏ qua các thuộc tính khác mà người ta có thể đặt trong mô hình, ví dụ như 'DataType'.
Markus

8

Không có bất kỳ EditorForghi đè nào cho phép bạn chuyển vào một đối tượng ẩn danh có thuộc tính bằng cách nào đó sẽ được thêm làm thuộc tính trên một số thẻ, đặc biệt là đối với các mẫu trình soạn thảo tích hợp. Bạn sẽ cần phải viết mẫu trình soạn thảo tùy chỉnh của riêng bạn và chuyển giá trị bạn muốn dưới dạng viewdata bổ sung.


2
@Html.EditorFor(m=>m.Created ...) 

không cho phép bất kỳ đối số nào được truyền vào cho hộp Văn bản

Đây là cách bạn có thể áp dụng các thuộc tính.

@Html.TextBoxFor(m=>m.Created, new { @class= "date", Name ="myName", id="myId" })

2

Sử dụng jQuery, bạn có thể thực hiện dễ dàng:

$("input").addClass("class-name")

Đây là thẻ đầu vào của bạn

@Html.EditorFor(model => model.Name)

Đối với DropDownlist, bạn có thể sử dụng cái này:

$("select").addClass("class-name")

Đối với danh sách thả xuống:

@Html.DropDownlistFor(model=>model.Name)

2

Trong khi câu hỏi được nhắm mục tiêu tại MVC 3.0, chúng tôi cũng thấy vấn đề vẫn tồn tại trong MVC 4.0. MVC 5.0 hiện bao gồm quá tải cho htmlAttribution.

Tôi buộc phải sử dụng MVC 4.0 tại nơi làm việc hiện tại của mình và cần thêm một lớp css để tích hợp JQuery. Tôi đã giải quyết vấn đề này bằng một phương pháp mở rộng duy nhất ...

Phương pháp mở rộng:

using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using System.Xml.Linq;

namespace MyTest.Utilities
{
    public static class MVCHelperExtensionMethods
    {
        public static MvcHtmlString AddHtmlAttributes(this MvcHtmlString input, object htmlAttributes)
        {
            // WE WANT TO INJECT INTO AN EXISTING ELEMENT.  IF THE ATTRIBUTE ALREADY EXISTS, ADD TO IT, OTHERWISE
            // CREATE THE ATTRIBUTE WITH DATA VALUES.

            // USE XML PARSER TO PARSE HTML ELEMENT
            var xdoc = XDocument.Parse(input.ToHtmlString());
            var rootElement = (from e in xdoc.Elements() select e).FirstOrDefault();

            // IF WE CANNOT PARSE THE INPUT USING XDocument THEN RETURN THE ORIGINAL UNMODIFIED.
            if (rootElement == null)
            {
                return input;
            }

            // USE RouteValueDictionary TO PARSE THE NEW HTML ATTRIBUTES
            var routeValueDictionary = new RouteValueDictionary(htmlAttributes);

            foreach (var routeValue in routeValueDictionary)
            {
                var attribute = rootElement.Attribute(routeValue.Key);

                if (attribute == null)
                {
                    attribute = new XAttribute(name: routeValue.Key, value: routeValue.Value);
                    rootElement.Add(attribute);
                }
                else
                {
                    attribute.Value = string.Format("{0} {1}", attribute.Value, routeValue.Value).Trim();
                }
            }

            var elementString = rootElement.ToString();
            var response = new MvcHtmlString(elementString);
            return response;
        }
    }
}

Cách sử dụng đánh dấu HTML:

@Html.EditorFor(expression: x => x.MyTestProperty).AddHtmlAttributes(new { @class = "form-control" })

(Đảm bảo bao gồm không gian tên của phương thức tiện ích mở rộng trong chế độ xem dao cạo)

Giải thích: Ý tưởng là đưa vào HTML hiện có. Tôi đã chọn phân tích thành phần hiện tại bằng cách sử dụng Linq-to-XML bằng cách sử dụng XDocument.Parse(). Tôi vượt qua các htmlAttribution như loại object. Tôi sử dụng MVC RouteValueDictionaryđể phân tích các htmlAttribution được truyền vào. Tôi hợp nhất các thuộc tính nơi chúng đã tồn tại hoặc thêm một thuộc tính mới nếu nó chưa tồn tại.

Trong trường hợp đầu vào không thể phân tích cú pháp bởi XDocument.Parse()tôi từ bỏ tất cả hy vọng và trả về chuỗi đầu vào ban đầu.

Bây giờ tôi có thể sử dụng lợi ích của DisplayFor (hiển thị các kiểu dữ liệu như tiền tệ một cách thích hợp) nhưng cũng có khả năng chỉ định các lớp css (và bất kỳ thuộc tính nào khác cho vấn đề đó). Có thể hữu ích để thêm các thuộc tính nhưdata-* , hoặc ng-*(Angular).


1

Bạn có thể tạo cùng một hành vi tạo một trình soạn thảo tùy chỉnh đơn giản có tên DateTime.cshtml, lưu nó trong Lượt xem / Chia sẻ / Trình soạn thảo

@model DateTime

@{
    var css = ViewData["class"] ?? "";
    @Html.TextBox("", (Model != DateTime.MinValue? Model.ToString("dd/MM/yyyy") : string.Empty), new { @class = "calendar medium " + css});
}

và theo quan điểm của bạn

@Html.EditorFor(model => model.StartDate, new { @class = "required" })

Lưu ý rằng trong ví dụ của tôi, tôi mã hóa cứng hai lớp css và định dạng ngày. Tất nhiên, bạn có thể thay đổi điều đó. Bạn cũng có thể làm tương tự với các thuộc tính html khác, như chỉ đọc, bị vô hiệu hóa, v.v.


1

Tôi đã sử dụng một giải pháp khác bằng cách sử dụng các bộ chọn thuộc tính CSS để có được những gì bạn cần.

Chỉ ra thuộc tính HTML mà bạn biết và đặt theo kiểu tương đối bạn muốn.

Giống như dưới đây:

input[type="date"]
{
     width: 150px;
}

1

Không cần tạo mẫu tùy chỉnh cho MVC 4. Sử dụng TextBox thay vì EditFor ở đây các thuộc tính html đặc biệt không được hỗ trợ, nó chỉ được hỗ trợ từ MVC 5. TextBox nên hỗ trợ cho MVC 4, tôi không biết về phiên bản khác.

@Html.TextBox("test", "", new { @id = "signupform", @class = "form-control", @role = "form",@placeholder="Name" })

0

Bạn cũng có thể làm điều đó thông qua jQuery:

$('#x_Created').addClass(date);

0

Tôi chỉ cần đặt kích thước của một hộp văn bản trên một trang. Các thuộc tính mã hóa trên mô hình và tạo các mẫu trình soạn thảo tùy chỉnh là quá mức cần thiết, vì vậy tôi chỉ gói cuộc gọi @ Html.EditorFor bằng một thẻ span gọi là một lớp chỉ định kích thước của hộp văn bản.

Khai báo lớp CSS:

.SpaceAvailableSearch input
{
    width:25px;
}

Xem mã:

<span class="SpaceAvailableSearch">@Html.EditorFor(model => model.SearchForm.SpaceAvailable)</span>

0

Một cách tốt nhất để áp dụng lớp vào @Html.EditorFor()trong MVC3 RAzor là

@Html.EditorFor(x => x.Created)


<style type="text/css">

#Created
{
    background: #EEE linear-gradient(#EEE,#EEE);   
    border: 1px solid #adadad;
    width:90%;
    }
</style>

Nó sẽ thêm phong cách trên vào của bạn EditorFor()

Nó hoạt động cho MVC3.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.