0

Been banging my head off the wall for a couple of days with this one and can't seem to figure it out or find an article that answers my question.

I'm working on a rota system for work, which is almost complete, but I'm stuck on this part in the admin area. It will allow management to edit multiple rota entries for a given date range, for a given team. It will eventually use a view model to pass in the dateFrom, dateTo, and Team (teamID) - I've just done it this way for now to try to get it working.

The rotas are stored in the Rotas table (see below.) Rotas table

MorningShift and EveningShift (both FK's) store the employee's payroll number e.g. 123456.

The employee details are stored in the TeamMembers table (see below.) TeamMembers table

The Username in the TeamMembers table is the employee's payroll number.

My issue is that I can't seem to get the currently entered value in the rotas table to display in the dropdown list in the view. It just has the first employee in the select list (Model.TeamMembers) displayed for all dropdowns. My question is, how do I get the current value to display in each dropdown in the view? I did try

    @Html.DropDownListFor(m => m.Rotas[i].MorningShift, Model.TeamMembers,
   Model.Rotas[i].TeamMember1.FirstName + " " + Model.Rotas[i].TeamMember1.Surname, null)

but while this shows the correct employee, it doesn't have a value set for the option, and obviously shows the employee's name again because that is in the selectlist.

What I have so far:

The controller:

    public async Task<ActionResult> ModifyRotas(DateTime? dateFrom,
            DateTime? dateTo, int? Team)
    {
        Auth auth = new Auth();
        bool isAdmin = auth.IsAdmin();

        if (!isAdmin)
        {
            return new HttpStatusCodeResult(HttpStatusCode.Unauthorized);
        }

        if (dateFrom != null && dateTo != null)
        {
            DateTime today = DateTime.Today;
            DateTime startDate = Convert.ToDateTime(dateFrom);
            DateTime endDate = Convert.ToDateTime(dateTo);

            // Make sure earlier shifts can't be modified
            if (startDate < today)
            {
                startDate = today;
            }


            // Verify the team exists
            Team teamDetails = await db.Teams.FindAsync(Team);
            if (teamDetails == null)
            {
                return HttpNotFound();
            }

            ModifyRotaVM vm = new ModifyRotaVM();

            // Get rotas for the team for the dates specified
            var rotas = await db.Rotas.Where(r => r.TeamID == Team && (r.ShiftDate >= startDate && r.ShiftDate <= endDate)).ToListAsync();

            vm.Rotas = rotas;

            // Generate the dropdown lists
            var teamMembers = db.TeamMembers.Where(m => m.TeamID == Team && m.Deleted == 0).Select(m => new SelectListItem() { Text = m.FirstName + " " + m.Surname, Value = m.Username });
            ViewBag.MorningShift = teamMembers;
            ViewBag.EveningShift = teamMembers;

            vm.TeamMembers = teamMembers;

            return View(vm);

        }

        // If we got here, something went wrong; redisplay the form
        return RedirectToAction("Modify");
    }

The VM:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;

    namespace TeamRota.Models
    {
       public class ModifyRotaVM
       {
          public List<Rota> Rotas { get; set; }

         public IEnumerable<SelectListItem> TeamMembers { get; set; }
       }
    }

The view:

    @model TeamRota.Models.ModifyRotaVM

    @{
       ViewBag.Title = "ModifyRotas";
    }

    <h2>Modify Rotas</h2>

    @using (Html.BeginForm("RotaMod", "Rotas", new { area = "Admin" },
    FormMethod.Post))
    {
    // Being passed in so we can redirect back to the same page after the update
    @Html.Hidden("startDate", Request.QueryString["dateFrom"])
    @Html.Hidden("endDate", Request.QueryString["dateFrom"])
    @Html.Hidden("TeamID", Request.QueryString["Team"])

    <table width="100%">
       <tr>
          <td>Shift date</td>
          <td>Morning shift</td>
          <td>Evening shift</td>
      </tr>

      @for (int i = 0; i < Model.Rotas.Count(); i++)
      {

         <tr>
            <td>
               @Html.HiddenFor(m => m.Rotas[i].ID)
               @Html.DisplayFor(m => m.Rotas[i].ShiftDate)
            </td>
            <td>@Html.DropDownListFor(m => m.Rotas[i].MorningShift, Model.TeamMembers, Model.Rotas[i].TeamMember1.FirstName + " " + Model.Rotas[i].TeamMember1.Surname, null)</td>
        <td>@Html.DropDownListFor(m => m.Rotas[i].EveningShift, Model.TeamMembers, Model.Rotas[i].TeamMember.FirstName + " " + Model.Rotas[i].TeamMember.Surname, null)</td>
    </tr>
    }

    <tr>
        <td colspan="4"><input type="submit" class="btn btn-success" value="Update" /></td>
    </tr>
    </table>

    }

Would really appreciate any help that anyone can offer.

Thanks.

Tom

Tom
  • 3
  • 2
  • Why do you incorporate this, `Model.Rotas[i].TeamMember1.FirstName + " " + Model.Rotas[i].TeamMember1.Surname` into your DropDownListFor? What's the purpose of using a label if you're modifying? The correct value should be displayed on page load if you're modifying.. A label should be used if you're creating. – Grizzly Aug 31 '17 at 14:56
  • I was trying to see if it would put the correct employee as automatically selected - I'm relatively new to asp.net and mvc – Tom Aug 31 '17 at 14:58
  • Which explains why it has no value correlated with it, along with it being shown again in the selectlist. I think this question's solution might be a little bit of test and see what happens.. so I'm going to post a solution even though it might not be correct initially. If not, we can work through it. – Grizzly Aug 31 '17 at 15:01

1 Answers1

0

I think you should try recreating your SelectList for the DropDownListFor.

var teamMembers = db.TeamMembers.Where(m => m.TeamID == Team && m.Deleted == 0).Select(m => new { Text = m.FirstName + " " + m.Surname, Value = m.Username });
ViewBag.TeamMembers = teamMembers

Then in your view, you just have to do this:

@Html.DropDownListFor(m => m.Rotas[i].MorningShift, new SelectList(ViewBag.TeamMembers, "Value", "Text", Model.Rotas[i].TeamMember1.Username), null)

@Html.DropDownListFor(m => m.Rotas[i].EveningShift, new SelectList(ViewBag.TeamMembers, "Value", "Text", Model.Rotas[i].TeamMember.Username), null)
Grizzly
  • 5,873
  • 8
  • 56
  • 109
  • How do I get the rota id into the select list? – Tom Aug 31 '17 at 15:21
  • I just edited my answer. See if that does it? – Grizzly Aug 31 '17 at 15:21
  • No. Getting a compiler error: Compiler Error Message: CS0121: The call is ambiguous between the following methods or properties: 'SelectExtensions.DropDownListFor(HtmlHelper, Expression>, IEnumerable, IDictionary)' and 'SelectExtensions.DropDownListFor(HtmlHelper, Expression>, IEnumerable, string)' – Tom Aug 31 '17 at 15:25
  • Okay I've edited a few times now haha, try taking out the `SelectListItem` when you're creating `var teamMembers`. Just create an anonymous class. See my edit – Grizzly Aug 31 '17 at 15:26
  • No, still not working. Error CS0266 Cannot implicitly convert type 'System.Linq.IQueryable<>' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?) – Tom Aug 31 '17 at 15:28
  • That is bc your property `TeamMembers` is of type `IEnumerable ` and you're trying to make it a anonymous list – Grizzly Aug 31 '17 at 15:33