KnockoutJS/Bootstrap - Clearing modal form when cl

2019-05-26 21:04发布

问题:

I have a Bootstrap Modal that contains a form for updating or creating an entity (Company in my example). Right now my issue is that if I view an entity using the modal, it doesn't clear out the fields when I close the modal by any means. Causing the form to still be populated if I then click a "Create" button, which should bring me up a blank modal.

How can I execute one of my ViewModels methods from just regular javascript? Here is some of my code:

function ViewModel() {
        var self = this;

       function CompanyViewModel(company) {
            var self = this;
            self.Id = company.CompanyId;
            self.Name = company.Name;
        }

        function BlankCompanyViewModel() {
            var self = this;
            self.Id = 0;
            self.Name = "";
        }

        self.company = ko.observable();
        self.companies = ko.observableArray();


        self.clearCurrentCompany = function() {
            self.company(new BlankCompanyViewModel());
        };

       // Initialize the view-model
        $.getJSON("/api/company", function(companies) {
            $.each(companies, function(index, company) {
                self.companies.push(new CompanyViewModel(company));
            });
            self.clearCurrentCompany();
        });
    }

Ideally I'd like to run ViewModel.clearCurrentCompany on the "Hidden" event of the modal like so:

 $('#myModal').on('hidden', function() {
       //Do something here, not sure what
    });

回答1:

function ViewModel() {
    var self = this;
    // your previous code
    $('#myModal').on('hide', function() {
       self.clearCurrentCompany();
    });
}

Just like that. Note that you want hide, not hidden, because hidden fires only after the modal completely disappears. If a user opens a create before the previous view closes, it will still be populated.



回答2:

I like to use a custom binding around a modal to make it open/close/display based on populating/clearing an observable.

Something like:

ko.bindingHandlers.modal = {
    init: function(element, valueAccessor, allBindings, vm, context) {
        var modal = valueAccessor();
        //init the modal and make sure that we clear the observable no matter how the modal is closed
        $(element).modal({ show: false, backdrop: 'static' }).on("hidden.bs.modal", function() {
            if (ko.isWriteableObservable(modal)) {
                modal(null);
            }
        });

        //apply the template binding to this element
        ko.applyBindingsToNode(element, { with: modal }, context);

        return { controlsDescendantBindings: true };
    },
    update: function(element, valueAccessor) {
        var data = ko.utils.unwrapObservable(valueAccessor());
        //show or hide the modal depending on whether the associated data is populated
        $(element).modal(data ? "show" : "hide");
    }
};

You then use this against an observable. It acts like a with binding against that observable and shows/hides the modal based on whether the observable is populated.

Here is a sample that shows this in use and sets up a subscription where you could run custom code when the modal is closed. http://jsfiddle.net/rniemeyer/uf3DF/