A
A
Andrey Matsovkin2014-01-23 21:03:56
JavaScript
Andrey Matsovkin, 2014-01-23 21:03:56

Knockout.js: how to properly extend the functionality of an observable variable (ko.observable)?

I'm using KnockoutJS .
I want to make it possible to edit the observed variable through a copy of the value, with the ability to apply changes or reset.
I do “expansion” through extenders ( description ).
The tasks are as follows:
1. to create a basic utility class common to various extensions
2. it is convenient to set functionality in each individual extension
3. to “contaminate” the extended variable with additional methods and properties as little as possible
4. to bypass (correctly handle) cases of calling extended methods from the interface, if the variable was not "expanded" for some reason.
I'm interested in your advice both on individual optimization and in general on the correctness of the implementation idea. Point 4 especially worries me.
Below is a primitive code to illustrate. Or he's on CodePen .

// базовый класс для различных расширений
var basicAction = function(p,o,t){
  var self = this;
  // пока здесь пусто. это «на вырост»
  self.allowed = o;
};
// расширяем функционал функциями редактирования
ko.extenders.editAction = function(t,o){
  var self = this;
  var Action = new basicAction('some',o,t);

  // основные методы за счет которых переменная получит новые возможности
  Action['fn'] = {
    editStart: function(item){ // начинаем редактирование переменной
      console.log('editStart:'+item);
    },
    editSave: function(item){ // созраняем измененное значение
      console.log('editSave'+item);
    },
    editCansel: function(item){ // откатываемся на начальное значение
      console.log('editCancel'+item);
    }
  };

  // создаем ф-и заглушки на случай «непредвиденного» вызова
  ko.utils.objectForEach(Action['fn'], function(actionName,action){
    Action[actionName] = function(){ // dump func
      console.log('dump func');
      return t;
    };
  });

  // если функционал редактирования включен
  if (Action.allowed) {
    // расширяем объект основными методами
    ko.utils.extend(Action, Action['fn']);
  }

  Action.actionSome = Action; // делаем ссылку на себя
  ko.utils.extend(t, Action); // добавляем функционал к observable переменной
  return t;
};

a = ko.observable(15).extend({editAction:true}); // подключаем возможность «редактирования с отменой»
a.editStart(); // просто проверяем вызов нужной ф-и — все ок
a.extend({editAction:false}); // отключаем функционал редактирования
a.editStart(); // проверяем, что ничего не происходит (срабатывает ф-я заглушка)

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question