I am new to knockout and readings it's tutorials for implementation.
I got to know about 2 different ways of writing view models in early chapters. I just need to know what is the difference between them.
I tried to figure out myself but may be not picking rights words.
Pdf i am refering to is Knockout PDF
There are several ways to create objects in javascript. The first one you're showing in your question is a literal. Another one is defining a constructor and invoking itt to get the object.
Yor AppViewModel is a constructor. If you need to use an instance of it as your viewmodel, you have to invoke the constructor, like this:
var vm = new AppViewModel();
ko.applyBindings(vm);
BTW, your fullName computed observable is incomplete. It's missing closing curly brakects, the second parameter, and closing parenthesis: }, self);
Related
I've to put two ko.applyBindings(); in the same function but the system turn me back a run-time error.
Is it possible to do that?
Usually, you create a viewModel object and then call ko.applyBindings(viewModel) once, like this:
var viewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable(123)
};
ko.applyBindings(myViewModel);
Maybe this is what you're looking?
Optionally, you can pass a second parameter to define which part of the document you want to search for data-bind attributes. For example, ko.applyBindings(myViewModel, document.getElementById('someElementId')). This restricts the activation to the element with ID someElementId and its descendants, which is useful if you want to have multiple view models and associate each with a different region of the page.
From the documentation here.
As for your comment about managing a list and an array, I'm not sure what you mean. They sound like the same thing to me. Knockout has observable arrays that you can use.
Is it possible to bind more than one data object to a template? I find the single object philosophy a bit resistant to scalability.
How can I add more observant data objects to a template without modifying the one already attached to it.
When you instanciate the ractive instance you could do something like this.
var r = new Ractive({data : {Object1:{},
Object2:{} } });
Then you can attached as many objects as you want.
Then you can scope this in your templates by doing
{{#Object1}}
<div>{{Prop1}}
{{/Obj1}}
{{#Object2}}
<div>{{PropForObject2}}
{{/Obj2}}
I have several knockout models, that I use on my website. Let's say for a given model I have a property
function modelA {
this.doSomething = function () { ... };
}
Now i want to use the doSomething() function in a different model. I would like to do this, such that I am not obligated to rewrite doSomething() in every single model that needs it. Ideally i would like it if this function becomes available as soon as ko.applyBindings(new modelX()) is called.
I know that i can have the functions inherit from a prototype, but that also leads repeated code in every single model. Is there a way to alter knockout.js to inject this property into all model objects?
EDIT:
In case there's a different approach that would achieve my desired goal, i'll elaborate on that desired goal. We use knockout-validation.js which allows me to call isValid() on every property in a model that has been extended with validation rules. I want to append a function to every model that will inspect the other properties in the model, and call isValid() on them. That way i can write a generic validation function that can be used with every model, without having to explicitly add it to the model.
You can add a custom function onto knockout's core datatypes. Alternatively you could look at extenders, and inside the extension you could add the function to an observable. Note, however, that both of these techniques address cross-cutting concerns at the "observable" level, not at the ViewModel level.
I would be curious to understand what doSomething is doing. Assuming that it has to access some observable(s) inside the ViewModel you should be able to reframe the problem so that the behaviour is attached to an observable.
I was trying to keep my code a bit cleaner by using the OOP patterns that MooTools provides in combination with Knockout.js
I can't seem to get it to work as Knockout returns some function (the property function, meh?) when it data binds the values. If the values are retrieved with javascript however, it works as exprected. I made a quick jsFiddle so you can test it out:
http://jsfiddle.net/tixz/JK2jt/
Thanks in advance!
In your current structure, the observables are created on the prototype of your class. Knockout does not intend on them being on the prototype (they can't be shared as they keep private state), and an internal function ko.isObservable fails, because of it. This causes the unwrapping code in KO does not realize that it needs to retrieve the underlying value for your observables.
You would have to write it like:
var ViewModel = new Class({
initialize: function(secondVal){
this.someProp = ko.observable('Here is my value');
this.anotherProp = ko.observable(secondVal);
}
});
http://jsfiddle.net/rniemeyer/JK2jt/9/
Coming from a Java background, I expect properties in the base class of an instance of a class to be unique from other class instances that use the same base class.
In javascript, any properties stored in "base class" appear to be shared between various instances of that "base class". For instance, see here:
http://jsfiddle.net/4waQV/
As you can see, BaseView.settings is accessed via both ViewOne and ViewTwo. Changing a value in BaseView.settings in one instance affects the value in the other instance.
If I move settings: {} out of BaseView and into ViewOne and ViewTwo, everything works the way I expect.
http://jsfiddle.net/4waQV/1/
However, I don't want to clutter up ViewOne and ViewTwo with extra properties. So I can dynamically create this.settings inside BaseView.setProp():
http://jsfiddle.net/4waQV/2/
Are there better ways to deal with this, or is this a good solution?
Note that I'm using Backbone.JS views in this example, but I expect than any javascript prototype inheritance solution would result similarly. You can see that Backbone uses fairly typical methods of creating prototypical inheritance:
https://github.com/documentcloud/backbone/blob/0.3.3/backbone.js#L870
https://github.com/documentcloud/backbone/blob/0.3.3/backbone.js#L955
The problem here is that settings is inherited from BaseView; inherited, not copied. If it were a string value it would be essentially copied, but in javascript arrays and objects are passed by reference, not by value, so when the object instantiates it ends up pointing at the same object.
The fix is to create an initialize method in your BaseView and add this line:
this.settings = {};
Then of course you'll want to make sure you call the BaseView initialize from each of your subviews. You can do that with:
BaseView.prototype.initialize.apply(this, arguments);
e.g. http://jsfiddle.net/taxilian/PDmN8/1/
Note that this method of initializing members needs to be done on all array or object members or you'll have the same issue. You could also create a constructor and do it there, but I've never been really clear on how those work in Backbone classes and haven't taken the time to really sit down and figure it out =]