0

I am doing a code challenge using Knockout.JS. It's pretty neat so far.

I have a couple simple questions on best practices, if someone could help me out. I'm trying to imagine what using this library will be like at a large scale but it's difficult.

When declaring the viewModel, is it usually better to only declare observables in the model when it's declared and tack on utility functions later? Or should functions integral to the viewModel be declared at the same time?

So this:

var viewModel = {
    newItemName: ko.observable(),
    newItemPrice: ko.observable(0),
    newItemQuantity: ko.observable(1)
};

viewModel.incrementUp = function() {
    var value = this.quantity() + 1;
    this.quantity(value);
};
// more functions here

ko.applyBindings(viewModel);

versus. this:

var viewModel = {
    newItemName: ko.observable(),
    newItemPrice: ko.observable(0),
    newItemQuantity: ko.observable(1),

    addNewItem: function () {
        var newItem = {
            name: capitalizeFirst(this.newItemName()),
            price: this.newItemPrice(),
            quantity: ko.observable(this.newItemQuantity())
            };
        }
    };

viewModel.something = ko.computed(function() {
     return 'do stuff'
});

ko.applyBindings(viewModel);

Or do people normally just add on computed values after? I don't know if people would appreciate monolithic viewModel literals or if there's a standard to how this should be approached. I am used to Angular having 'the Angular way' to do everything, haha.

Sorry for being so pedantic. As I said, it's a code challenge and I want to impress...plus I am finding very difficult to find examples of Knockout apps.

Thanks!

joh04667
  • 6,035
  • 18
  • 30
  • Have you see this part of the documentation?: http://knockoutjs.com/documentation/computedObservables.html#a-popular-convention-that-simplifies-things – JohnnyHK Jun 24 '16 at 03:33
  • If you want to impress, use ES2015, e.g. modern Javascript. Babel will do the transpile for you. And you can get rid of self = this. – brianlmerritt Jun 24 '16 at 05:28
  • The "PS" of my answer is still applicable by the way, I don't think you can get option two (the "versus" option) to work at all. I.e. option 2 is not an option. (If you can get it to work, please amend your question and ping me so I can adjust my answer accordingly.) – Jeroen Jun 24 '16 at 08:01

2 Answers2

1

Use neither option, except for things like small tests and repros. There are better options.

PS. Note that your second example is even wrong, the this keyword inside addNewItem will not refer to the view model!

The full answer to the underlying question would be way too broad for Stack Overflow. The underlying question is something like this:

How to create reusable code / View Models with proper encapsulation in Javascript?

Realize that you're asking a rather broad question, and accept the fact that you'd need to read / learn quite a bit before you can know the answer. I recommend starting by reading up on prototypal (also called "prototypical") and classical inheritance in Javascript, as well as the more modern class features of modern ECMA Script, Typescript, etc.

To leave you with a concrete tip for more easily creating view models with computeds, here's an example that uses "Constructor Functions", which will work in all modern (and some slightly older) browsers without extra libraries or transpilation steps:

function ViewModel() {
  // Keep a reference to the instance of the view
  // model, becauese "this" itself might behave in
  // unexpected ways within functions inside this
  // view model constructor function.
  var self = this;

  self.firstName = ko.observable("john");
  self.surname = ko.observable("doe");

  self.fullname = ko.computed(function() {
     return self.firstName() + " " + self.surname();
  });
}

// Use it like this:
var johndoe = new ViewModel();

It utilizes the self=this idiom as well as Constructor Functions (also a side-note recommendation in the KO docs).

Community
  • 1
  • 1
Jeroen
  • 53,290
  • 30
  • 172
  • 279
  • Thanks for the answer. To clarify, I am not new to Javascript and I have been developing in Angular for some time, so I am no stranger to shenanigans with `this`. I had just copy/pasted the `addNewItem` from existing code outside the object literal and didn't notice the `this`. My question was more regarding if viewmodels are more commonly declared as constructors or object literals, and if object literals should only observables be declared in literals. – joh04667 Jun 24 '16 at 07:42
  • Ah, wrong tone of my answer then, apologies. I'll leave it like this though, for others with similar questions but less JS background. The base advise remains: use constructor functions, view model factory functions, or modern ES class features to create view models; not object literals. – Jeroen Jun 24 '16 at 07:59
0

It depends on the situation.

For me, I like to keep anything that's strictly to do with the view model in the model, and then if I need specific functionality added for a specific use of the view model, I can add it later.

This means I can create a reusable model/view model, and taylor it to my specific needs if/when required.

AndrewP
  • 1,488
  • 9
  • 22