Question

I am learning knockout and came with one problem. There are two add buttons, One for 'Add New Make' and another 'Add new Model'. When I click 'Add', I want to open a modal popup and enter the text either car make or car model based on which button I click. I want to share same modal popup but want to display different title and text in the modal as well. When I click 'Add New Model', I want to pass MakeId of car as well. Below is my ViewModel. I believe there is better way of doing. Please correct me if I am wrong !!

$(function () {
var VehicleBasic = function () {
    var self = this;
    self.VIN = ko.observable();
    self.selectedYear = ko.observable();
    self.Years = ko.observableArray([]);
    self.selectedMake = ko.observable();
    self.Makes = ko.observableArray([]);
    self.NewMake = ko.observable();
    self.selectedModel = ko.observable();
    self.MyModels = ko.observableArray([]);
    self.NewModel = ko.observable();
    self.Styles = ko.observableArray([]);
    self.selectedStyle = ko.observable();
    self.ShowModels = ko.computed(function () {
        if (self.selectedMake())
            return true;
        return false
    });
    self.ClearAddMake = function () {
        self.NewMake('');
    };
    self.AddNewMake = function (NewMake) {
        debugger;
        $.ajax({
            url: "ChromeOptimization.aspx/AddMake",
            async: false,
            data: JSON.stringify({ 'make': NewMake.NewMake() }),
            dataType: "json",
            type: 'POST',
            contentType: "application/json; charset=utf-8",
            success: function (data) {
                $.each(data.d, function (index, v) {
                    self.Makes.push(v);
                });
            }
        });
    };
    self.ClearAddNewModel = function () {
        self.NewModel('');
    };
    self.AddNewModel = function (newModel) {
        debugger;
        $.ajax({
            url: "ChromeOptimization.aspx/AddNewModel",
            async: false,
            data: JSON.stringify({ 'makeId': self.selectedMake(), 'model': newModel }),
            dataType: "json",
            type: 'POST',
            contentType: "application/json; charset=utf-8",
            success: function (data) {
                $.each(data.d, function (index, v) {
                    self.Makes.push(v);
                });
            }
        });
    };
}
var viewModel = new VehicleBasic();
var vin = '';
$.ajax({
    url: "ChromeOptimization.aspx/GetBase",
    async: false,
    data: { vin: vin },
    dataType: "json",
    type: 'GET',
    contentType: "application/json; charset=utf-8",
    success: function (data) {
        viewModel.Makes(data.d.Makes);
        viewModel.VIN = data.d.VIN;
        viewModel.Years = data.d.Years;
        viewModel.selectedMake(data.d.selectedMake);
    }
});
viewModel.selectedMake.subscribe(function (makeId) {
    viewModel.MyModels.removeAll();
    viewModel.selectedModel(undefined);
    viewModel.selectedStyle(undefined);
    if (makeId != undefined || makeId != null) {
        $.ajax({
            url: "ChromeOptimization.aspx/GetModels",
            async: false,
            data: { MakeId: makeId },
            dataType: "json",
            type: 'GET',
            contentType: "application/json; charset=utf-8",
            success: function (data) {
                $.each(data.d, function (index, v) {
                    viewModel.MyModels.push(v);
                });
                viewModel.selectedModel(undefined);
            }
        });
    }
});
viewModel.selectedModel.subscribe(function () {
    viewModel.Styles.removeAll();
    viewModel.selectedStyle(undefined);
    if (viewModel.selectedMake() && viewModel.selectedModel()) {
        $.ajax({
            url: "ChromeOptimization.aspx/GetStyles",
            async: false,
            data: { makeId: viewModel.selectedMake(), modelId: viewModel.selectedModel() },
            dataType: "json",
            type: 'GET',
            contentType: "application/json; charset=utf-8",
            success: function (data) {
                $.each(data.d, function (index, v) {
                    viewModel.Styles.push(v);
                });
                viewModel.selectedStyle(undefined);
            }
        });
    }
})
ko.applyBindings(viewModel, $('#divBasicInformation').get(0));

})

Was it helpful?

Solution

You should check custom bindings in knockout. Here is one simplest custom binding for modal pop which you can use in your case:

ko.bindingHandlers.modal = {
  init: function (element, valueAccessors) {
       var options = ko.utils.unwrapObservable(valueAccessors() || {});    

       $(element).modal(options);
   },
   update: function (element, valueAccessors) {
       var options = ko.utils.unwrapObservable(valueAccessors() || {});

       $(element).modal(options.show() ? 'show' : 'hide');
   }
};

What i understand is that you want a single modal markup code which should be reusable for all modals. This thing is possible with many different ways out of which one is with binding in knockout.Here is the code which demonstrate the use:

Check this fiddle

JS

function modal(data)
{
  var self = this;

  self.title = data.title || 
    'Default title';
  self.message = data.message || 
    'Default message';
  self.confirmButtonText = data.confirmButtonText || 
    'Default text';
  self.confirmAction = data.confirmAction || 
    function() { alert("Default action"); };
}

function vm()
{
  var self = this;

  self.addMake = function() { alert("Maked added"); };

  self.addCar = function() { alert("Car added"); };

  self.MyModels = ko.observableArray([
    new modal({ 
      title: "Add new make", 
      message: "This modal will add new make.",
      confirmButtonText: "Add make", 
      confirmAction: self.addMake 
    }),
    new modal({ 
      title: "Add new car", 
      message: "This modal will add new car.",
      confirmButtonText: "Add car", 
      confirmAction: self.addCar 
    })
  ]);

  self.modalVisible = ko.observable(false);

  self.SelectedModal = ko.observable(self.MyModels()[0]);

  self.openModal = function(data, event)
  {
    self.SelectedModal(data);
    self.modalVisible(true);
  };

  self.closeModal = function(data, event) { self.modalVisible(false); };
} 

Html

<div class="modal fade" data-bind="modal: { backdrop: 'static', keyboard: false, show: modalVisible }">
    <div class="modal-dialog" data-bind="with: SelectedModal">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-bind="click: $root.closeModal">&times;</button>
                <span class="modal-title"><span data-bind="text: title"></span></span>
            </div>
            <div class="modal-body">
                <div class="row">
                    <div class="col-md-12">
                        <span data-bind="html: message"></span>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default" data-bind="click: $root.closeModal">Cancel</button>
                <button type="button" class="btn btn-danger" data-bind="click: confirmAction, text: confirmButtonText"></button>
            </div>
        </div>
    </div>
</div>

Hope is helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top