How do I access a component viewModel from the outside?

4,267 views
Skip to first unread message

shead....@gmail.com

unread,
Dec 2, 2014, 10:06:33 PM12/2/14
to knock...@googlegroups.com
Gang:

The component binding documentation at http://knockoutjs.com/documentation/component-binding.html demonstrates creating a pair of "message-editor" components, with-and-without parameters.  However, I don't see how a parent viewModel would retrieve values entered by the user in those components?  It seems that I could create observables in my parent viewModel and pass them to the "child" components as parameters, but that seems like it really limits the usefulness of components - for example, I'd like to combine components that each wrap multiple UI widgets, and read values out of their view models when the user chooses "Save".  I'm hoping I'm missing something?

Cheers!
Tim

termin...@gmail.com

unread,
Dec 3, 2014, 3:11:04 PM12/3/14
to knock...@googlegroups.com
As far as I'm aware, sending observables via a component's parameters is the way to ensure the value is tracked properly while inside the component.  For example: http://jsfiddle.net/mkb7c475/

In your example,  the "Save" function could be defined on the parent ViewModel, and it would only need to check the values of its own observable, which may or may not have been modified in one or more components.

function SomeModel() {
   
this.Prop1 = ko.observable();
   
this.ComponentProp1 = ko.observable();
   
this.ComponentProp2 = ko.observable();
}

function ViewModel() {
   
var self = this;
   
self.selectedItem = ko.observable(); //Represents SomeModel

   
self.save = function() {
         
var data = ko.toJSON(self.selectedItem());
         
//Do server stuff here  
   
};

   
self.edit = function(item) {
     
self.selectedItem(item);
   
};
}

<!-- ko with: selectedItem -->
<comp1 params="prop: componentProp1"></comp1>
<comp2 params="prop: componentProp2"></comp2>
<!-- /ko -->

I believe you could then chain observable properties of an observable parameter into other components.

shead....@gmail.com

unread,
Dec 10, 2014, 12:20:59 PM12/10/14
to knock...@googlegroups.com, termin...@gmail.com
Thanks for the suggestion, it definitely works, although the lack of encapsulation bugs me - it feels wrong to be allocating storage in a parent for use in a child component.  However, I've successfully experimented with a couple of alternatives, each with their own pros and cons:

* Passing a parent observable as a parameter to the component, where it assigns self to the observable.
* Using ko.dataFor() to retrieve the component model from a DOM element.  Note that when using custom elements, you have to use ko.dataFor() on one of the templated DOM elements, not the containing custom element, as the latter will return the parent model.

Cheers,
Tim

Chris Holland

unread,
Dec 19, 2014, 7:26:54 PM12/19/14
to knock...@googlegroups.com, termin...@gmail.com

shead....@gmail.com

unread,
Jan 12, 2015, 12:22:02 AM1/12/15
to knock...@googlegroups.com, termin...@gmail.com
Great suggestion, I was completely unaware that knockout had pub-sub builtin.  Many thanks!
Tim
Reply all
Reply to author
Forward
0 new messages