user2433629
user2433629

Reputation: 11

Knockout JS query from newbie - help needed please

I am creating an input field which updates a div on keypressdown. So, if the user types 'test' into the input field, the div is populated with the text 'test'.

This is pretty simple and working fine. However, I need it to create multiple divs for multiple words. So, if the user types 'hello world' there will be two divs created - one for 'hello' and one for 'world'.

How do I go about this?

I've set up a JS Fiddle if that helps:

http://jsfiddle.net/dYK3n/60/

This is my JS:

var viewModel = {
    styleChoices: ["yellow", "red", "black", "big"],
    style: ko.observable("yellow"),
    text: ko.observable("text"),
};

ko.applyBindings(viewModel);

All help appreciated.

Thanks in advance.

Upvotes: 1

Views: 97

Answers (3)

Darussian
Darussian

Reputation: 1593

Here is a fiddle http://jsfiddle.net/dYK3n/81/

var ViewModel = function(){
var self = this;enter code here
this.styleChoices= ["yellow", "red", "black", "big"],
this.style = ko.observable("yellow"),
this.text = ko.observable("new text"),
this.numberOfWords = ko.computed(function(){
    return self.text().split(" ").length;
}),
this.getWordFromIndex = function(index){
    return self.text().split(" ")[index];
}
};

ko.applyBindings(new ViewModel());




<div data-bind="foreach:new Array(numberOfWords())">
 <div class="phrase" data-bind="text:$parent.getWordFromIndex($index()),css:$parent.style"></div>   
</div>

Sorry i dont have time for a better explaination, if you have questions ill answer them when i can

Upvotes: 0

deltree
deltree

Reputation: 3824

Here's a working fiddle.

First thing's first, you need to be able to refer to your viewModel from inside a computed observable for this to work, so I changed it to a function.

var viewModel = function() {
    var self = this;

By identifying the viewModel as a variable, we can assign it properties, much like you were doing in javascript object style.

self.styleChoices =  ["yellow", "red", "black", "big"];
self.style = ko.observable("yellow");
self.textField = ko.observable("new text");

I renamed your text object to textField just for keyword differentiation. Now you chose to work with a raw array of text. In the future it may be wise to work with an object, but for now this is a simple string split. See the split() method.

self.textItem = ko.computed(function() {
    var txt = self.textField();
    var result = [];
    if (txt != null && txt.length > 0)
    {
        result = txt.split(" ");
    }
    return result;
});

I used a Knockout Computed function so that it is expected to grab values from other fields. Finally, in order to reproduce this div based on the number of items in this new computed array, we need to use a template. Do further reading on Html Templates.

<script type="text/html" id="text-template">
    <div class="phrase" data-bind="css: $root.style, text: $data"></div>
</script>

And we call that template from a foreach template binding. See Template Binding.

<div data-bind="template: { name: 'text-template', foreach: textItem }"></div>

In order to grab the raw text, we use $data and in order to grab the css style from the root model we use $root. See Binding Context.

data-bind="css: $root.style, text: $data"

Upvotes: 4

vdwijngaert
vdwijngaert

Reputation: 1555

I don't see why you should use KnockOut for this.

Just use the split() method to split on spaces and put the results in an array. Loop through that array and create a div for each word in the array.

Upvotes: 0

Related Questions