Reputation: 173
I've got a custom component which uses functions to pass in the parameters. In this case the observable value ($data) is not changing, but the function makes use of another observable (which is changing) and a hash table (which is changing, but cannot be made observable).
The display updates when I use this syntax:
<span style="width: 50px; position: absolute; left: 1100px;text-align:center" data-bind="component: {name: ''rotate'', params: {values: Helper.GetWeatherByFlight($data, ''Hi'')}}"></span>
But it does not update when I use this syntax:
<rotate style="width: 50px; position: absolute; left: 1100px;text-align:center" params="{values: Helper.GetWeatherByFlight($data, ''Hi'')}"></rotate>
This is the component:
ko.components.register('rotate', {
viewModel: function (params) {
var values = [];
var inputValues = ko.isObservable(params.values) ? params.values() : params.values;
var length = inputValues.length;
this.MyClass = length > 1 ? "fade-effect" : "";
if (length >= 1) {
var index = m_counter % length;
$.each(inputValues, function (i, value) {
var opacity = (index == i) ? 1 : 0;
values.push({ value: value, opacity: opacity });
});
}
this.values = values;
},
template: '<span style="position:relative;" data-bind="foreach: values, attr: { class: MyClass }">\
<span style="left:0px;top:0px;position:absolute;width:100%;height:100%;" data-bind="text: Helper.GetValue(value, $element), style: {opacity: opacity}"></span>\
</span>'
});
I'd prefer to be able to use the second format, but for now I am stuck with the first. Is there something I can change, either in the component, or the way that the component is called, so make both formats update properly? I realize that this is a somewhat unconventional usage.
Upvotes: 1
Views: 1167
Reputation: 4304
The only reason your component refreshes in the first case is that the component binding is looking for changes, and then re-initializes the entire component when it detects any.
The rotate component itself isn't treating your parameters like they're observable it's only looking at the unwrapped values so there's nothing to tell it to refresh its view. You'll need to rewrite the component view-model to use observables and computed properties so that it can react to changes in the data.
Something like this:
viewModel: function (params) {
var self = this;
this.inputValues = params.values; //preserve the observable instead of unwrapping its values
this.MyClass = ko.observable("");
//values is a computed property so that it updates when the dependent observable (inputValues) is modified.
this.values = ko.computed(function(){
var values = [];
//use ko.unwrap to safely handle either case of inputValues being an observable or non-observable.
var length = ko.unwrap(self.inputValues).length;
self.MyClass(length > 1 ? "fade-effect" : "");
if (length >= 1) {
var index = m_counter % length;
$.each(ko.unwrap(self.inputValues), function (i, value) {
var opacity = (index == i) ? 1 : 0;
values.push({ value: value, opacity: opacity });
});
}
return values;
});
},
Upvotes: 1