0

I have a simple form of sales information which users edit comments and reasons and then using the SaveChanges() function the data gets committed back to the database. I need to update a field which contains an ID number. I have a simple dropdownlist (populated by a viewbag) and when the user makes a change I want to update the ID number in the hiddenfor field so it can be posted back on save. My code is below:

EditorTemplate

   <tr>
@Html.HiddenFor(modelItem => modelItem.ID)
@Html.HiddenFor(modelItem => modelItem.tblTaggingGroupID)
@Html.HiddenFor(modelItem => modelItem.FinYear)
@Html.HiddenFor(modelItem => modelItem.FinWeek)
@Html.HiddenFor(modelItem => modelItem.WeekDay)
@Html.HiddenFor(modelItem => modelItem.Segment)
@Html.HiddenFor(modelItem => modelItem.NetSales)
@Html.HiddenFor(modelItem => modelItem.SwellSales)
@Html.HiddenFor(modelItem => modelItem.SpikeSales)
@Html.HiddenFor(modelItem => modelItem.BaseSales)
@Html.HiddenFor(modelItem => modelItem.tblTaggingReasonID)
<td>
    @switch (Model.WeekDay)
    {
        case 1:
            @:Sunday
            break;
        case 2:
            @:Monday
            break;
        case 3:
            @:Tuesday
            break;
        case 4:
            @:Wednesday
            break;
        case 5:
            @:Thursday
            break;
        case 6:
            @:Friday
            break;
        case 7:
            @:Saturday
            break;
        default:
            break;
    }
</td>
<td>
    @Html.DisplayFor(modelItem => modelItem.Segment)
</td>

<td>
    @Html.DisplayFor(modelItem => modelItem.NetSales)
</td>
<td>
    @Html.DisplayFor(modelItem => modelItem.SwellSales)
</td>
<td>
    @Html.DisplayFor(modelItem => modelItem.SpikeSales)
</td>
<td>
    @switch (Model.Recurring)
    {
        case true:
            Model.Recurring.ToString();
            break;
        case false:
            Model.Recurring.ToString();
            break;
        default:
            break;
    }
    @Html.EditorFor(modelItem => modelItem.Recurring)
</td>

<td>@Html.DropDownListFor(modelItem => modelItem.tblTaggingReasonID, (SelectList)ViewBag.Reasons, "Please Select")</td>
<td>
    @Html.EditorFor(modelItem => modelItem.Comment, new { @class = "Commenttxt" })
</td>

Controller:

        public ActionResult Index()
    {
        var SelectedID = Convert.ToInt32(Session["_SessionSelectGroupID"]);
        var SelectedYear = Convert.ToInt32(Session["_SessionSelectFinYear"]);
        var SelectedWeek = Convert.ToInt32(Session["_SessionSelectFinWeek"]);
        var tblTaggingGroupInstances = db.tblTaggingGroupInstances.Include(t => t.tblTaggingGroup);

         ViewBag.Reasons = new SelectList(db.tblTaggingReasons,"ID","UpliftReason");

        return View(tblTaggingGroupInstances.Where(t => t.tblTaggingGroupID == SelectedID && t.FinYear == SelectedYear && t.FinWeek == SelectedWeek).ToList());
    }
    [HttpPost]
    public ActionResult Index(List<tblTaggingGroupInstance> model)
    {
        foreach (var record in model)
        {
            db.Entry(record).State = EntityState.Modified;
        }
        db.SaveChanges();
        return RedirectToAction("Details");
    }

I'm assuming this can be done with some simple JQuery or Javascript but, everything I have tried so far falls over?

Readamus
  • 43
  • 2
  • 11
  • 2
    Why? Just bind the dropdownlist to the property - `@Html.DropDownList(m => m.tblTaggingReasonID, (SelectList)ViewBag.Reasons, "Please Select")` There is no need for javascript –  Feb 17 '16 at 10:06
  • Unbelievable! That's effectively what I was wanting to achieve but couldn't quite work out what to do! Thanks! – Readamus Feb 17 '16 at 10:12
  • Note also that you appear to be generating a collection, in which case, this will not pre-select the correct option if `tblTaggingReasonID` has an existing value - you need to pass the `SelectList` to the `EditorTemplate` as `additionalViewData` - refer [this answer](http://stackoverflow.com/questions/31174250/how-to-set-default-value-to-select-list-in-mvc-during-run-time/31174308#31174308) for an explanation –  Feb 17 '16 at 10:16
  • thanks - I managed to pick up on that one as I was testing, a problem I am having though is posting the changed value back - it seems EF is not picking up that the entity value has been changed in the dropdown list. – Readamus Feb 18 '16 at 10:30
  • The value should be posted back fine based on the code you have shown. But your only generating form controls for properties `Recurring`, `tblTaggingReasonID` and `Comment` - there is not even an ID to indicate to EF which object to save. And all the other properties would be saved as their defaults even if it did work. –  Feb 18 '16 at 11:20
  • As always, use a view model. Then bind to the view model and post it back, then for each item in the model, get the corresponding data model (based on the ID), update its properties from the view model and then save the data model. –  Feb 18 '16 at 11:21
  • 1
    OK, I see what you have done now based on the edit. You have included `@Html.HiddenFor(modelItem => modelItem.tblTaggingReasonID)` which needs to be deleted. Your posting back 2 values for the same property and the hidden input is first so the `DefaultModelBinder` sets the value from the hidden input (which is the initial value) and ignores the 2nd one (the value of the selected option) –  Feb 18 '16 at 11:55
  • good spot - I had missed that. Thanks – Readamus Feb 18 '16 at 12:01

2 Answers2

1

There is no need to use javascript to update the hidden input. Instead just bind directly to the property

@Html.DropDownList(m => m.tblTaggingReasonID, (SelectList)ViewBag.Reasons, "Please Select")

and remove the hidden input from the view.

  • the hidden input is needed to hold the value when post back to controller. if the dropdownlist is disabled (according to certain requirements), we need the hidden input to hold the value https://stackoverflow.com/questions/1636103/html-dropdownlist-disabled-readonly – Kristina Lex Jan 27 '23 at 06:58
0

Attach change() event with #Reasons and update #tblTaggingReasonID value. As shown :-

$("#Reasons").on("change",function(){
   $("#tblTaggingReasonID").val(this.value)
});

Don't forget to include jQuery file in your page.

Kartikeya Khosla
  • 18,743
  • 8
  • 43
  • 69