1

I'm having some trouble accessing model objects from my view model. This is likely just a JavaScript/KnockoutJS familiarity issue, so any help is appreciated. Here's my code:

<!-- VIEW -->
<select data-bind="options: allTypes, 
                   optionsCaption: 'Choose...',                   
                   value: chosenType"></select>
<div data-bind="text: chosenType"></div>
<div data-bind="text: chosenValues"></div> <!-- << This line not working -->
<script type="text/javascript">

/*-- VIEW MODEL --*/
function ViewModel() {
    this.chosenType=ko.observable();
    this.chosenValues=allValues[this.chosenType]; // <-- Problem here?
}

/*-- MODEL --*/
var allTypes=["Animals","Plants","Minerals"];
var allValues={
    "Animals":["Pig","Big pig","Owl"],
    "Plants":["Aloe","Fern"],
    "Minerals":["Bauxite","Chromite"]
    };

    ko.applyBindings(new ViewModel());
</script>

I think the problem is likely in how this.chosenValues is being declared. Thanks for reading.

3
  • Is there some reason you aren't providing an argument to ko.observable()? Commented Nov 18, 2015 at 1:32
  • Thanks for the comment. There's no argument to ko.observable because this.chosenType doesn't need a default value, and I think that part's working OK. Commented Nov 18, 2015 at 1:35
  • Can you inspect new ViewModel()? Is viewModel.chosenValues returning undefined? Commented Nov 18, 2015 at 1:39

1 Answer 1

1

The text binding is for single values only, not collections/arrays. You can use the foreach binding to list each item i.e.

<div data-bind="foreach: chosenValues">
    <span data-bind="text: $data"></span>
</div>

Or you can use a computedObservable i.e.

function ViewModel() {
   this.chosenType=ko.observable();
   // computed value is evaluated if an observable value changes
   // this creates a comma separated string of values
   // you'll probably want safety checks here but just a quick sample
   this.chosenValues=ko.computed(function() {
        var chosenVals=allValues[this.chosenType()];
        return chosenVals.join(', ');
   }, this);
}

Also remember to update the UI from a model, you will need some form of observable. In your example chosenValues is not an observable so will not update the UI if a selection changes.

Also see https://jsfiddle.net/51oufny4/ for a working sample

Edit ** Here is the sample provided in the above fiddle:

<!-- VIEW -->
<select data-bind="options: allTypes, 
               optionsCaption: 'Choose...',                   
               value: chosenType"></select>
<div data-bind="text: chosenType"></div>
<div data-bind="text: chosenValues"></div>
<script type="text/javascript">

/*-- VIEW MODEL --*/
function ViewModel() {
    this.chosenType=ko.observable();
    this.chosenValues=ko.computed(function(){
        return allValues[this.chosenType()];
    }, this);
}

/*-- MODEL --*/
var allTypes=["Animals","Plants","Minerals"];
var allValues={
    "Animals":["Pig","Big pig","Owl"],
    "Plants":["Aloe","Fern"],
    "Minerals":["Bauxite","Chromite"]
};

ko.applyBindings(new ViewModel());
</script>
Sign up to request clarification or add additional context in comments.

3 Comments

Hey, thanks for this! I swapped in the foreach code and made this.chosenValues an observable: this.chosenValues=ko.observable(allValues[this.chosenType]); No luck yet. Am I missing something?
Looks like I partially lied (my apologies). Looks like the text binding automatically creates a comma separated string. You're forgetting to evaluate your observable chosenType. Remember chosenType is an observable and you need to unwrap to get the underlying value. See my fiddle here: jsfiddle.net/51oufny4
The fiddle works great, thanks! If you want to update this answer with the working code from the fiddle, I'll mark it as accepted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.