Reputation: 136
I've read some other questions about basic JavaScript and I know that to have a variable available across two functions you need to do a return or make the variable global (outside the function).
But I think the solution in knockout could be even simpler (or perhaps, the whole structuring of my code is completely off and I could make it something more better).
Basically, here's what I wanted to accomplish:
<h4 data-bind="text: displayTheValue">The value should be displayed here</h4>
<select data-bind="options: htmlSelectSet, optionsText: 'theText', optionsValue: 'theValue', value: displayTheValue"></select>
<p><span data-bind:"text: charSymbol">I want to display a character here that is dependent on the choices of the dropdown above</span></p>
I have there the HTML template that relies on Knockout to generate content. Here's the JS:
function thisViewModel() {
var self = this;
var num1 = numeral(35450).format('0,0'); //variables probably set by input?
var num2 = numeral(2450).format('0,0');
self.htmlSelectSet = [{
theText: "alpha",
theValue: num1
}, {
theText: "bravo",
theValue: num2
}];
self.displayTheValue = ko.observable();
}
ko.applyBindings(new thisViewModel());
What I've achieved so far is populating the drop down with items, and the values of the drdop down are displayed in to
<h4 data-bind="text: displayTheValue">
and with the help of a nifty numeralsJS library it's formatted properly into a comma'ed number (Yay).
Now, what I'm trying to achieve is, when the user chooses alpha on the dropdown, the
<span data-bind:"text: charSymbol"></span>
up there will output "A".
Do I make another function for that, which would be dependent on the theText value?
I did this:
function setChar() {
var self = this;
if (thisViewModel().theText == "alpha") {
showSymbol = "A";
}
if (thisViewModel().theText == "bravo") {
showSymbol = "B";
}
else {
currencySymbol = null;
}
self.showSymbol = ko.observable();
}
ko.applyBindings(new setChar());
Thinking just making a function that calls out thisViewModel().theText would do something, but currently doesn't work.
I'll appreciate any kind of tip. I don't think this is way too complex but it's driving me pickles.
I'll also appreciate tips on how to structure and approach problems (i.e. using multiple functions is better or simply put everything in one function?)
(For reference: my JavaScript skills are Novice; weird - why am I hammering in with libraries like Knockout when at average the best thing I know in JS is to output "Hello Word" with a string character count? I don't know, probably just brave :D The last programming language I was very good at was way back in Turbo C. But I will learn!)
Thanks!
Upvotes: 1
Views: 135
Reputation: 7958
You can use a computed observable
. There is no need to have two view models.
What if you’ve got an observable for firstName, and another for lastName, and you want to display the full name? That’s where computed observables come in - these are functions that are dependent on one or more other observables, and will automatically update whenever any of these dependencies change.
http://knockoutjs.com/documentation/computedObservables.html
First change your value binding to set the object to displayTheValue instead of just the value by removing optionsValue: 'theValue'
.
Since the object can now be undefined we need to put some some protection around the text binding. If it's undefined we will just set the text to empty string. We could also used the with binding instead:
<h4 data-bind="text: displayTheValue() ? displayTheValue().theValue : ''"></h4>
Then fix the issue in your symbol span as you were using :
instead of =
:
<span data-bind="text: charSymbol"></span>
Now for the computed. When displayTheValue then the computed function will fire and return the relevant value:
self.charSymbol = ko.computed(function () {
if (self.displayTheValue()) {
if (self.displayTheValue().theText == "alpha") {
return "A";
}
if (self.displayTheValue().theText == "bravo") {
return "B";
}
}
return null;
});
http://jsfiddle.net/yku33mtq/1/
Upvotes: 2