Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undo change on cancel button

I am trying to cancel the changes done during my page edit. But whenever I click on cancel, the updated changes are reflected. How to revert the changes on click of cancel button. Any help on this will be really helpful since I am new to knockout
https://jsfiddle.net/tan2dgsa/

// ViewModel.js

var viewModel = {

    articles: [{
        id: 1,
        title: "KnockOut Templating",
        content: "Content for Knockout goes here."
    }, {
        id: 2,
        title: "SharePoint 2013 REST API",
        content: "Content for SharePoint."
    }, {
        id: 3,
        title: "Knockout with SharePoint",
        content: "Content for knockout and SharePoint."
    }],

    selectedTemplate: ko.observable("readOnly"),
    selectedMode: ko.observable(),    
};

viewModel.currentTemplate = function (tbl) {
    return tbl === this.selectedMode() ? 'editMode' : this.selectedTemplate();
}.bind(viewModel);

viewModel.reset = function (t) {
    this.selectedMode("editMode");
};
ko.applyBindings(viewModel);
like image 798
user4324324 Avatar asked May 25 '16 05:05

user4324324


2 Answers

You ask a rather broad question, or it is fact a To Do:

Create rollback functionality on KnockoutJS based edit forms

The question behind that to do is: what is the idiomatic way to do that in KnockoutJS? The answer is: there is none. You need to write something yourself.

The basic idea behind any solution will be the same: save a copy of the original data from before editing so you can revert to it upon canceling.

Here are two good ways to do that:

  1. Use a library, e.g. ko.editables is designed for exactly this purpose.
  2. Do It Yourself. It's actually not that hard: you save the model behind the view model upon initialization, and upon "save", and reuse the initialize method on "cancel".

Here's some sample code for the latter:

var dummyItem = { id: 42, name: "John doe" };

function ItemViewModel(data) {
  var self = this, currentDto = data;
  
  self.id = ko.observable();
  self.name = ko.observable();
  
  self.isInEditMode = ko.observable(false);
  
  self.reset = function() {
    self.id(currentDto.id);
    self.name(currentDto.name);
    self.isInEditMode(false);
  };
  
  self.saveState = function() {
    currentDto = {
      id: self.id(),
      name: self.name()
    };
    self.isInEditMode(false);
  };
  
  self.reset();
}

function RootViewModel() {
   var self = this;
   self.items = ko.observableArray([new ItemViewModel(dummyItem)]);
   
   self.startEdit = function(item) { item.isInEditMode(true); };
   self.save = function(item) { item.saveState(); };
   self.cancel = function(item) { item.reset(); };
}

ko.applyBindings(new RootViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>

<ul data-bind="foreach: items">
  <li>
    <span data-bind="text: id"></span>
    <span data-bind="text: name"></span>
    <input data-bind="textInput: name, visible: isInEditMode">
    <button data-bind="visible: !isInEditMode(), click: $root.startEdit">edit</button>
    <button data-bind="visible: isInEditMode, click: $root.save">save</button>
    <button data-bind="visible: isInEditMode, click: $root.cancel">cancel</button>
  </li>
</ul>

You should probably try to implement one of these two options for your own context. If you run into specific problems, I suggest getting back to SO with specific questions.

like image 79
Jeroen Avatar answered Sep 20 '22 21:09

Jeroen


If you're using KO Mapping plugin, this will be quite simple.

Hold parameter 'data' in another local variable, say 'originalData', and then simply call mapping plugin's function to re-map data.

For ex.,

    var myKOViewModel = function(data) {
        var self = this;
        var originalData = data;
        ko.mapping.fromJS(data, null, self);    // ViewModel initial mapping


        //....

        self.CancelClicked = function () {
            ko.mapping.fromJS(originalData, null, self);        // Refresh ViewModel
        }
    }

Please refer to KO's documentation https://knockoutjs.com/documentation/plugins-mapping.html for more details.

like image 38
Kris Avatar answered Sep 20 '22 21:09

Kris