0

I need to create a View where I can add additional forms for user input. The form has several dropdownlists. I'm trying to add another form when the user clicks "Add New" button, but I am unable to figure out how to do it as well as how to bind the dropdownlists in the partial view.

Below is the code in the main View:

  @using (Html.BeginForm())
    {
        <form class="autoWidth">
            <h4 class="hr">
                <a class="btn btn-danger icon-subtract sm btn-xs" data-nodrag ng-click="remove(this)"></a>
            </h4>
            <div class="">
                <span class="inline-block">
                    @Html.LabelFor(model => model.LoanClasses, new { @class = "control-label" })
                    @Html.DropDownListFor(model => model.SelectedLoanClass, Model.LoanClasses, new { @class = "inputROW" })
                </span>   
                <span class="inline-block">
                    @Html.LabelFor(model => model.LoanPurpose, new { @class="control-label"})
                    @Html.DropDownListFor(model => model.SelectedLoanPurpose, Model.LoanPurpose, new { @class = "inputROW" })

                </span>
                <span class="inline-block">
                    @Html.LabelFor(model => model.AmountRequested, new { @class = "control-label" })
                    @Html.TextBoxFor(model => model.AmountRequested, new{@class="inputROW"})
                </span>  
                <span class="inline-block">
                    @Html.LabelFor(model => model.RequestedRate, new { @class = "control-label" })
                    @Html.TextBoxFor(model => model.RequestedRate, new { @class = "inputROW" })
                </span> 
            </div>
            <div class="breakup">
                <span class="inline-block">
                    @Html.LabelFor(model => model.LoanTypes, new { @class = "control-label" })
                    @Html.DropDownListFor(model => model.SelectedLoanType, Model.LoanTypes, new { @class = "inputROW" })
                    <span id="types-loading-progress" style="display: none;">Please wait...</span>
                </span>
                <span class="inline-block">
                    @Html.LabelFor(model => model.RateIndex, new { @class = "control-label" })
                    @Html.DropDownListFor(model => model.SelectedRateIndex, Model.RateIndex, new { @class = "inputROW" })
                </span>
                <span class="inline-block">
                    @Html.LabelFor(model => model.OriginationFeePercentage, new { @class = "control-label" })
                    @Html.TextBoxFor(model => model.OriginationFeePercentage, new { @class = "inputROW" })
                </span>
            </div>
            <div class="breakup">
                <span class="inline-block">
                    @Html.LabelFor(model => model.VariableRateFloor, new { @class = "control-label" })
                    @Html.TextBoxFor(model => model.VariableRateFloor, new { @class = "inputROW" })
                </span>
                <span class="inline-block">
                    @Html.LabelFor(model => model.VariableRateCeiling, new { @class = "control-label" })
                    @Html.TextBoxFor(model => model.VariableRateCeiling, new { @class = "inputROW" })
                </span>
                <span class="inline-block">
                    @Html.LabelFor(model => model.VariableRateMargin, new { @class = "control-label" })
                    @Html.TextBoxFor(model => model.VariableRateMargin, new { @class = "inputROW" })
                    </span>
             </div>
            <div class="breakup">
                <span class="inline-block">
                    @Html.LabelFor(model => model.PaymentType, new { @class = "control-label" })
                    @Html.DropDownListFor(model => model.SelectedPaymentType, Model.PaymentType)
                </span>
                <span class="inline-block">
                    @Html.LabelFor(model => model.PaymentPeriod, new { @class = "control-label" })
                    @Html.DropDownListFor(model => model.SelectedPaymentPeriod, Model.PaymentPeriod)
                </span>
                <span class="inline-block">
                    @Html.LabelFor(model => model.NumberOfPayments, new { @class = "control-label" })
                    @Html.TextBoxFor(model => model.NumberOfPayments, new { @class = "inputROW" })
                </span>
                <span class="inline-block">
                    @Html.LabelFor(model => model.AmortizationTerm, new { @class = "control-label" })
                    @Html.TextBoxFor(model => model.AmortizationTerm, new { @class = "inputROW" })
                </span>
            </div>

        </form>
    }
    <div id="newrow">
    <div><input id="addBtn" type="button" value="Add New" /></div>
</div>

<script>
    $("#addBtn").on("click", function () {

        $.get('@Url.Action("AddNewRow")', function () {
            $('#newrow');
        });

    });
</script>
<script type="text/javascript">
    $(function () {
        $("#SelectedLoanClass").change(function () {
                 var selectedItem = $(this).val();
                 var ddlTypes = $("#SelectedLoanType");
              var typesProgress = $("#types-loading-progress");
             typesProgress.show();
             $.ajax({
                 cache: false,
                 type: "GET",
                 url: "@(Url.RouteUrl("GetLoanTypesByClass"))",
                    data: { "LoanClassId": selectedItem },
                    success: function (data) {
                        ddlTypes.html('');
                        $.each(data, function (id, option) {
                            ddlTypes.append($('<option></option>').val(option.id).html(option.name));
                        });
                        typesProgress.hide();
                    },
                    error: function (xhr, ajaxOptions, thrownError) {
                        alert('Failed to retrieve types.');
                        typesProgress.hide();
                    }
                });
            });
        });
</script> 

The partial view has the exact same code in between @Html.BeginForm{} as the Main View (it is supposed to be an identical form).

Below is the code from my controller. the "New" method fills the Main View:

[HttpGet]
    [Route("New")]
    public async Task<ActionResult> New()
    {

        var loanClasses = await GetLoanClasses();
        var loanTypes = await GetLoanTypes();
        var loanPurposes = await GetLoanPurposes();
        var rateIndex = await GetRateIndex();
        var paymentPeriod = GetPaymentPeriodList();
        var paymentTypes = await GetPaymentTypes();


       var model = new LoanRequestRowViewModel();

        model.LoanClasses.Add(new SelectListItem {Text = "-Please Select-", Value ="-1"});
        foreach(var _class in loanClasses)
        {
            model.LoanClasses.Add(new SelectListItem()
                {
                    Text = _class.Text.ToString(),
                    Value = _class.Value.ToString()
                });
        }

        model.LoanTypes.Add(new SelectListItem { Text = "-Please Select-", Value = "-1" });
        foreach(var _type in loanTypes)
        {
            model.LoanTypes.Add(new SelectListItem()
                {
                    Text = _type.Text.ToString(),
                    Value = _type.Value.ToString()
                });
        }

        model.LoanPurpose.Add(new SelectListItem { Text = "-Please Select-", Value = "-1" });
        foreach(var purpose in loanPurposes)
        {
            model.LoanPurpose.Add(new SelectListItem()
                {
                    Value = purpose.Value.ToString(),
                    Text = purpose.Text.ToString()
                });
        }

        model.RateIndex.Add(new SelectListItem {Text ="-Please Select-", Value = "-1"});
        foreach (var index in rateIndex)
        {
            model.RateIndex.Add(new SelectListItem()
                {
                    Value = index.Value.ToString(),
                    Text = index.Text.ToString()
                });

        }
        foreach(var period in paymentPeriod)
        {
            model.PaymentPeriod.Add(new SelectListItem()
                {
                    Value = period.Value.ToString(),
                    Text = period.Text.ToString()
                });
        }
        model.PaymentType.Add(new SelectListItem{Text="-Please Select-", Value ="-1"});
        foreach(var paytype in paymentTypes)
        {
            model.PaymentType.Add(new SelectListItem()
                {
                    Value = paytype.Value.ToString(),
                    Text = paytype.Text.ToString()
                });
        }



        return View(model);
    }

I was trying to use the following to add the partial View. The View did try to load (I had different code in the script, but it was still incorrect), but it kept throwing "object not set to an instance.." when it tried to render the dropdownlists on the partial. Hence I have two problems, rendering the partial on click of Add Button, and binding the dropdownlists on the partial once it is rendered.

   [HttpGet]
        [Route("Create")]
        public ActionResult AddNewRow()
        {

            return PartialView("_newLoanRequest");
        }

Any assistance will be greatly appreciated!

I realized that I was not explaining this well so here is what the result should look like:

Loan Request 1

Loan Class     Loan Purpose    Requested Amount, etc. etc.

Loan Type       Rate Index     Origination Fee, etc. etc.


Loan Request 2

Loan Class     Loan Purpose    Requested Amount, etc. etc.

Loan Type      Rate Index      Origination Fee, etc. etc. 

Loan Request 3

Loan Class      Loan Purpose      Requested Amount, etc. etc.

Loan Type       Rate Index        Origination Fee, etc. etc.

I was trying to use the partial view to keep rendering new blank loan requests. They want each of them to show in a sort of list like above. If there is a better way to achieve the desired results, any guidance is appreciated!

BeeDev
  • 13
  • 1
  • 7
  • To add the new row, try `$.get('@Url.Action("AddNewRow")', function (data) { $('#newrow').html(data);});` but its unclear what your trying to do with the code you have shown. –  Sep 20 '14 at 21:36
  • And you are not passing a model to the view in the `AddNewRow()` method –  Sep 20 '14 at 21:48
  • When I tried to pass the model to the view in AddNewRow() it gave me an error on the dropdownlist saying that they had no data. Technically, the "row" that I am trying to add is not really a row, it is a partial view with entirely new form exactly like the one in the main view beginning with @Html.BeginForm. The #newrow div is where I want the partial view to display. – BeeDev Sep 21 '14 at 16:37
  • I guess what really needs to happen as the AddNewRow button needs to save the first record in the main view then render the partial view (which just is another identical empty form as the main view). Do I need to include all of the same code I have in the controller that populates the dropdownlists on the main view? I'm not sure if I am explaining myself correctly, but it sure seems that you know what you are doing, so I hope you can help me. – BeeDev Sep 21 '14 at 16:54
  • Not clear exactly what you are trying to do (sorry but it makes no sense and in any case clicking `AddNewRow` wont save the first record), but you need to pass a model to your partial that includes the `SelectList`s otherwise `@Html.DropDownListFor(model => model.SelectedLoanPurpose, ...` will throw an exception because `model.SelectedLoanPurpose` is null. If the partial is the same as the code in the main view, then why not just replace all that code with `@Html.Partial("_YourPartial", Model)` to avoid the duplication. –  Sep 21 '14 at 22:34
  • Note also,` AddNewRow` is going to create another form with duplicate ID's (invalid html) and the `$("#SelectedLoanClass").change(function () {...` function will not work –  Sep 21 '14 at 22:40
  • I get what you are saying. The reason I am not replacing the main view with the partial is because They want each new request to show Like the the following: Loan Request 1 data, data data, then underneath it.... Loan Request 2 data, data, data, then Loan Request 3 data, data, data. That's why I was trying to use a partial view to keep adding Loan Requests. – BeeDev Sep 22 '14 at 12:43
  • Are you wanting to post all these (Loan Request 1, Loan Request 2 etc) back to the controller (to save them all)? –  Sep 22 '14 at 13:00
  • YES! I TRULY appreciate your help! Each Loan Request has a new GUID as its idea with an ApplicationId foreign key. – BeeDev Sep 22 '14 at 13:29
  • In order to post back a collection you need indexed names for each controls and using a partial view want do this. [This answer](http://stackoverflow.com/questions/24026374/adding-another-pet-to-a-model-form/24027152#24027152) may help you get started, although unless you want to edit them all at the same time I would consider a different approach where you display (read only) current loan requests and add (edit) new loan requests one at a time. –  Sep 22 '14 at 22:02

0 Answers0