0

I have a table template and table as below in MVC view

Template for dynamic row

<table id="Newrelation" style="display:none">
    <tr>
        <td>
            <select id="relation-%" style="width:100px" class="relation_type" name="survey_detail[#].relation" value></select>
        </td>
        <td>
            <select id="agegroup-%" style="width:100px" class="age_group" name="survey_detail[#].age_group" value></select>
        </td>
        <td>
            <select id="nodependent-%" style="width:100px" class="no_dependent" name="survey_detail[#].no_dependent" value></select>
            <input type="hidden" id="new_relation" name="survey_detail.Index" value="%" />
        </td>
        <td><input id="delete" class="delete" value="X" type="button"></td>
    </tr>
</table>

Actual table

<table id="relation" class="table table-striped table-hover table-bordered">
    <tbody>
        <tr>
            <th style="width:100px">
                Relation
            </th>
            <th style="width:150px">
                Age Group
            </th>
            <th style="width:150px">
                No: Dependent
            </th>
        </tr>
        @if (Model != null)
        {
            for (int i = 0; i < Model.survey_detail.Count; i++)
            {
                <tr>
                    <td>
                        @Html.DropDownListFor(m => m.survey_detail[i].relation, (SelectList)@ViewBag.Relation,"--", new { @class = "m-wrap" })
                    </td>
                    <td>
                        @Html.DropDownListFor(m => m.survey_detail[i].age_group, (SelectList)@ViewBag.Agegroup,"--", new { @class = "m-wrap" })
                    </td>
                    <td>
                        @Html.DropDownListFor(m => m.survey_detail[i].no_dependent, (SelectList)@ViewBag.Number, "--", new { @class = "m-wrap" })
                        <input type="hidden" name="survey_detail.Index" value="@i" />
                    </td>
                    <td><input id="delete" class="delete" value="X" type="button"></td>
                </tr>
            }
        }
    </tbody>
<table>

Jquery to attach new row on button click

$('#add_rel').click(function (e) {
    var body = $('#relation').children('tbody').first();
    var index = (new Date()).getTime();
    var clone = $('#Newrelation').clone();
    clone.html($(clone).html().replace(/\[#\]/g, '[' + index + ']'));
    clone.html($(clone).html().replace(/"%"/g, '"' + index + '"'));
    clone.html($(clone).html().replace(/"relation-%"/g, 'relation-' + index));
    clone.html($(clone).html().replace(/"agegroup-%"/g, 'agegroup-' + index));
    clone.html($(clone).html().replace(/"nodependent-%"/g, 'nodependent-' + index));
    var newrow1 = clone.find('tr');
    body.append(newrow1);
});

And it attach new row to the table but all the select list comes blank eventhough the @ViewBag.Relation,@ViewBag.agegroup,@ViewBag.Number has data.

Please guide me to get values on the select list

Sachu
  • 7,555
  • 7
  • 55
  • 94
  • The ` –  Jun 01 '16 at 11:20
  • @StephenMuecke can i give option property in template with the viewbag? – Sachu Jun 01 '16 at 11:21
  • As a side note, your use of `DropDownListFor()` inside a loop will not work correctly - the first option will always be selected when the page is initially displayed –  Jun 01 '16 at 11:22
  • @StephenMuecke can u pls show one eg? – Sachu Jun 01 '16 at 11:23

1 Answers1

1

Firstly, your use of DropDownListFor() will not work correctly (the first option will always be selected no mater what the value of the property is) as explained in this answer (note in your case you will not be able to use the EditorTemplate option).

To solve this and the main issue in your question, change your ViewBag properties from IEnumerable<SelectListItem> to IEnumerable<T> where T is an object containing just 2 properties, for example

public class OptionVM
{
    public int ID { get; set; }
    public string Name { get; set; }
}

and then the code in the GET method would be something like

ViewBag.Relation = db.Relations.Select(x => new OptionVM
{
    ID = x.RelationId,
    Name = x.SomeOtherPropertyToDisplay
});

In the view, for the generating the existing items, use

for (int i = 0; i < Model.survey_detail.Count; i++)
{
    ....
    @Html.DropDownListFor(m => m.survey_detail[i].relation, 
        new SelectList(ViewBag.Relation, "ID", "Name", Modelsurvey_detail[i].relation), 
        "--", 
        new { @class = "m-wrap" })
    ....
}

which will ensure the correct options is selected.

Now you can use those same ViewBag properties to add the <option> elements to your template when the page is first loaded.

// Get the first select element in the template
var relationSelect = $('#Newrelation').find('select').eq(0);
// Create a javascript array of the options
var relationOptions = @Html.Raw(Json.Encode(ViewBag.Relations));
// Create and append option elements
relationSelect.append($('<option></option>').val('').text('--'));
$.each(relationOptions, function(index, item) {
    relationSelect.append($('<option></option>').val(item.ID).text(item.Name));
});

and repeat for the 2nd and 3rd <select> elements in the template.

Side notes:

  1. It is not necessary to add id attributes to the <select> and <input type="hidden"> elements in the template and you should not be adding one to the <input type="button"> because that is generating invalid html (duplicate id attributes).
  2. Your creating a null ("--") option which suggest you will be validating that a selection has been made, in which case you should also be adding @Html.ValidationMessageFor() for each property (and adding the html that it generates to your template (refer this answer for more detail). If that is the case, you will also need to reparse the validator each time a new item is added (as shown in the previous link).
  3. Finally, I recommend you use a view model containing properties for the collections used to generate the options rather than using ViewBag.
Community
  • 1
  • 1
  • `var relationOptions = '@Html.Raw(Json.Encode(ViewBag.Relation)';` giving error `Unterminated string literal. Strings that start with a quotation mark (") must be terminated before the end of the line. However, strings that start with @ and a quotation mark (@") can span multiple lines` – Sachu Jun 02 '16 at 04:41
  • Oops - just noticed I was missing a closing `)` - should be `var relationOptions = '@Html.Raw(Json.Encode(ViewBag.Relation))';` - see edit - but let me check there are no other typos by creating the fiddle. –  Jun 02 '16 at 04:56
  • Found another as well (there should be no quotes). See [this DotNetFiddle](https://dotnetfiddle.net/kHN3en) for a working example (note I'll delete the fiddle in a few hours so fork it if you want to keep it) –  Jun 02 '16 at 05:04
  • thanks for your help..but still the select list is getting empty..the fiddle also when i run the select list don't have any value – Sachu Jun 02 '16 at 05:09
  • The fiddle works fine so not sure what your saying - the html is just `` and has no options - and its the script which is adding the 4 options to it. –  Jun 02 '16 at 05:13
  • for me when the fiddle runs the selectlist is blank :( – Sachu Jun 02 '16 at 05:15
  • What? Close it and click on the link again (sometimes it can be a bit slow and you can get a timeout exception) –  Jun 02 '16 at 05:16
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113583/discussion-between-sachu-and-stephen-muecke). – Sachu Jun 02 '16 at 05:17