Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC Editor-Templates/UIHint with parameters

I've been using Editor-Templates in the past like this, by applying the following data annotation:

[UIHint("SomeTemplate")]   

ViewModel:

 public class MicroViewModel  {     public IEnumerable<LabMicro> Micros { get; set; }      [UIHint("DateTime")]     public DateTime Date { get; set; }      public int CaseNo { get; set; }      [UIHint("SampleTypes")]     public int LabSampleTypeID { get; set; }      [UIHint("SampleDetails")]     public int LabSampleDetailID { get; set; }  } 

If I wanted to use a specific date picker control as opposed to the regular one, it can be implemented as follows.

Example:

@model DateTime?     @Html.TextBox("",  String.Format("{0:yyyy-MM-dd}", Model.HasValue ?          Model : DateTime.Today), new { @class = "dp", style="width:100px" })  <script type="text/javascript">         $(document).ready(function () {             $(".dp").datepicker({                 changeMonth: true,                 changeYear: true,             dateFormat: 'yy-mm-dd'             });         });       </script>   

For my ID fields, I'd like to make use of the jQuery auto-complete component.

Question:

How would I go about passing additional parameters to the UIHint partial view for LabSampleTypeID and LabSampleDetailID? (As Id like to have an auto-complete Editor-Template that'll take a URL and property names for example)

What I think my auto-complete Editor-Template/Partial should look like:

$(".auto").autocomplete({     source: function(request, response) {         $.ajax({             url: '[#URL_TO_USE]',             dataType: "json",             data: {                 filter: request.term             },             success: function(data) {                 response($.map(eval(data), function(item) {                     return {                         label: item.[#PROPERTY_TO_USE]                     }                 }));             }         })     } }); 
like image 714
Rohan Büchner Avatar asked Mar 13 '12 09:03

Rohan Büchner


2 Answers

You could use the AdditionalMetadata attribute:

[UIHint("DateTime")] [AdditionalMetadata("foo", "bar")] public DateTime Date { get; set; } 

and in the template:

@ViewData.ModelMetadata.AdditionalValues["foo"] 

so if you wanted to pass an url:

[UIHint("DateTime")] [AdditionalMetadata("controller", "somecontroller")] [AdditionalMetadata("action", "someaction")] [AdditionalMetadata("property", "someproperty")] public DateTime Date { get; set; } 

and in your template:

@{     var values = ViewData.ModelMetadata.AdditionalValues; }  <script type="text/javascript"> $('.auto').autocomplete({     source: function (request, response) {         $.ajax({             url: '@Url.Action((string)values["action"], (string)values["controller"])',             dataType: "json",             data: {                 filter: request.term             },             success: function (data) {                 response(                     $.map(eval(data), function (item) {                         return {                             label: item['@values["property"]']                         }                     })                 );             }         });     }                     }); </script> 
like image 163
Darin Dimitrov Avatar answered Sep 20 '22 16:09

Darin Dimitrov


You could use the UHint without AdditionalMetadata attribute, but some additional code is requred

[UIHint("DateTime", null, "key1", "value1", "key2", "value2")] public DateTime Date { get; set; } 

override CreateMetadata:

public class CustomMetadataProvider : DataAnnotationsModelMetadataProvider     {         public const string UiHintControlParameters = "UiHintControlParameters";          protected override ModelMetadata CreateMetadata(             IEnumerable<Attribute> attributes,             Type containerType,             Func<object> modelAccessor,             Type modelType,             string propertyName)         {              ModelMetadata metadata = base.CreateMetadata(                 attributes,                 containerType,                 modelAccessor,                 modelType,                 propertyName);              IEnumerable<UIHintAttribute> uiHintAttributes = attributes.OfType<UIHintAttribute>();             UIHintAttribute uiHintAttribute = uiHintAttributes.FirstOrDefault(a => string.Equals(a.PresentationLayer, "MVC", StringComparison.OrdinalIgnoreCase))                                               ?? uiHintAttributes.FirstOrDefault(a => String.IsNullOrEmpty(a.PresentationLayer));             if (uiHintAttribute != null)             {                 metadata.AdditionalValues.Add(UiHintControlParameters, uiHintAttribute.ControlParameters);             }              return metadata;         } 

Register CustomMetadataProvider:

    public static void Application_Start()     {         ModelMetadataProviders.Current = new CustomMetadataProvider();     } 

and in your template:

    @{         IDictionary<string, object> values = (IDictionary<string, object>) ViewData.ModelMetadata.AdditionalValues[CustomMetadataProvider.UiHintControlParameters];     } 
like image 42
Sel Avatar answered Sep 20 '22 16:09

Sel