Justin Helgerson
Justin Helgerson

Reputation: 25551

How to use an editor template with a default object instance

In my view file I current have the following code:

    @if ((Model.CustomerOrderTrackings != null) && (Model.CustomerOrderTrackings.Count > 0)) {
        for (int i = 0; i < Model.CustomerOrderTrackings.Count; i++) {
            @Html.EditorFor(m => m.CustomerOrderTrackings[i])
        }
    } else {
        @*The problem is here*@
        @Html.EditorFor(m => new CustomerOrderTracking())
    }

Then, my editor template looks like this:

@model Models.CustomerOrderTracking

<tr class="gridrow">
    <td class="carrierName">
        @Html.HiddenFor(m => m.Id, new { id = "" })
        @Html.HiddenFor(m => m.ShipperId, new { id = "", @class = "trackingShipperId" })
        @Html.DropDownListFor(m => m.CarrierName, ViewExtensions.ToFriendlySelectList<CustomerOrderTracking.CarrierNames>(Model.CarrierName), new { id = "" })
    </td>
    <td class="service">@Html.DropDownListFor(m => m.ShippingType, ViewExtensions.ToFriendlySelectList<CustomerOrderTracking.ShippingTypes>(Model.ShippingType), new { id = "" })</td>
    <td class="trackingNumber">@Html.TextBoxFor(m => m.ShippingTrackingNumber, new { @class = "trackingInput", id = "" }) <a href="" target="_blank" class="icon track"></a></td>
    <td class="shippingCost">
        @Html.TextBoxFor(m => m.ShippingCost, new { @class = "shippingInput", id = "" })
        <div onclick="Operations.Orders.DeleteTrackingRow(this)" class="icon delete deleteTracking" title="Delete this shipment?"></div>
    </td>
</tr>

What I'm trying to do is add a default row to this table in the event that there aren't currently any items attached to the object. The new instance of the object isn't working, since that results in the following error: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

I could hand-code the inputs, but then my code is rather sloppy since I'd be using hand-coded inputs and then auto-generated inputs from the ASP.NET MVC extensions.

Is there a way that I can pass a default instance of the object to my editor template?

Upvotes: 0

Views: 212

Answers (2)

MTran
MTran

Reputation: 1809

In my view file I current have the following code:

@if ((Model.CustomerOrderTrackings != null) && (Model.CustomerOrderTrackings.Count > 0)) {
    for (int i = 0; i < Model.CustomerOrderTrackings.Count; i++) {
        @Html.EditorFor(m => m.CustomerOrderTrackings[i])
    }
} else {
    @*The problem is here*@
    @Html.EditorFor(m => new CustomerOrderTracking())
}

The workaround is to declare an instance of your model outside of the Html EditorFor. For example:

@if ((Model.CustomerOrderTrackings != null) && (Model.CustomerOrderTrackings.Count > 0)) {
    for (int i = 0; i < Model.CustomerOrderTrackings.Count; i++) {
        @Html.EditorFor(m => m.CustomerOrderTrackings[i])
    }
} else {
    @{ CustomerOrderTracking stubModel = new CustomerOrderTracking(); }
    @Html.EditorFor(m => stubModel)
}

Upvotes: 0

Erik Philips
Erik Philips

Reputation: 54646

The way I see it, in an MVC framework, the way to accomplish what you want is to detect your requirement in the controller and adjust the model as necessary before it reaches the view. The other answer, that is 99% not the religiously property way to do it, is to have logic in your view (ew!).

public ActionResult SomeAction()
{

  if (model.CustomerOrderTrackings == null 
      || model.CustomerOrderTrackings.Count > 0) 
  {
    // Do Something with model
  }

  this.View(model)
}

Upvotes: 1

Related Questions