0

I have a MVC 5 Application on it I have 3 different tabs - they load the same Partial View via ajax details on Car Model and the Tabs are Diesel/Petrol/Electric so a user can enter details such a Engine Size across the 3 Tabs and this is saved to the DB.

I am using knockout js to call an ajax method to calculate some totals on the screen and also dynamically add content to the form and then save to the db. However - when I click between Tabs I get knockout throwing an error saying: You cannot apply bindings multiple times to the same element

Some of the markup for my page is below:

<div class="row" data-bind='foreach: ExtraCarInfos'>
                <div class="row">
                    <div class="col-xs-2">
                        <input type="hidden" data-bind="value: Id, attr: {name: 'ExtraCarInfos['+ $index() + '].Id'}"/>
                        <input type="text" data-bind="value: Name, attr: {name: 'ExtraCarInfos['+ $index() + '].Name'}" class = "form-control input-sm" />
                    </div>
                    <div class="col-xs-7">
                        <input type="text" data-bind="value: Description, attr: {name: 'ExtraCarInfos['+ $index() + '].Description'}" class="form-control input-sm" />
                    </div>
                    <div class="col-xs-2">
                        <input type="text" data-bind="value: ExtraValue, attr: {name: 'ExtraCarInfos['+ $index() + '].ExtraValue'}" class="form-control input-sm" data-calculate="true" />
                    </div>
                    <div class="col-xs-1">
                        <a href='#' data-bind='click: removeExtraInfo'>Remove</a>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="col-xs-12"><a href='#' data-bind='click: addExtraInfo'>Add Extra Info</a></div>
            </div>
            <div class="row">
                    @Html.TextBoxFor(model => model.Value,
                        new
                        {
                            @data_calculate = true
                        })
            </div>
            <div class="row">
                    @Html.TextBoxFor(model => model.Total,
                        new
                        {
                            @disabled = "disabled",
                            @data_bind = "value: Total"
                        })
            </div>

The js for the page is:

 var mvcModel = @Html.Raw(Json.Encode(Model))

    var createExtraCarInfo = function (data) {
            if (data) {
                return ko.mapping.fromJS(data);
            } else {
                return {
                    Id: ko.observable(),
                    Name: ko.observable(),
                    Description: ko.observable(),
                    ExtraValue: ko.observable()
                };
            }
        };

        var viewModel = ko.mapping.fromJS(mvcModel, {
            'ExtraCarInfos': {
                create: function(options) { return createExtraCarInfo(options.data); }
            }
        });


        // calculateTotal ajax method removed for Brevity

        var currentTab = fuelType + 'Content ';

        // Add subscription to update totals
        $('#' + currentTab).on('keyup', '[data-calculate]', calculateTotal);

        ko.applyBindings(viewModel);

        removeExtraInfo = function(item) {
            viewModel.ExtraCarInfos.remove(item);
        };

        addExtraInfo = function() {
            viewModel.ExtraCarInfos.push(createExtraCarInfo());
        };

I've looked at the following question - is there no way I can clear knockout bindings simply for all elements on the screen at once?

Community
  • 1
  • 1
Ctrl_Alt_Defeat
  • 3,933
  • 12
  • 66
  • 116
  • I believe the intended approach is to initially bind your view model to a DOM element on the page (see below), then bind the view model to any subsequently loaded elements when they are loaded by doing this: `ko.applyBindings(viewModel, document.getElementById("my-element-id-here"));` Clearing out bindings is not intended, which is why it is more difficult to do so... presumably because it leaves things in an incorrect state. – Pricey Aug 12 '14 at 11:04
  • @Pricey - so if I am using the same partial view across three Tabs what would be the best way to achieve this - give each element an Id including the FormName - i.e Diesel/Petrol and then apply bindings to that id? – Ctrl_Alt_Defeat Aug 12 '14 at 11:40
  • On the initial load of the page, if you have some data binding on the page then apply the knockout binding to only the element that is not partially loaded. Then when you partial load your tab content, call ko.applyBindings(...) on just the partially loaded content, I dont think these should need different names, as long as you have an ID to bind to. – Pricey Aug 12 '14 at 13:21

0 Answers0