Mapping a single string to an array.

1,188 views
Skip to first unread message

Stacey

unread,
Feb 15, 2012, 11:37:38 AM2/15/12
to knock...@googlegroups.com
I was curious if anyone had attempted to do this, but I essentially wish to create a binding that will take a single text input and split its values by a delimiter (generally a comma) and bind it to an observable array.

has anyone done such a thing? 

rpn

unread,
Feb 15, 2012, 9:29:07 PM2/15/12
to knock...@googlegroups.com
I think that you could use a couple options besides a custom binding.

1- if you the resulting array needs to be editable, then you could use a manual subscription against your original value that keeps an observableArray updated whenever the original value is updated.

2- otherwise, if you just want it computed each time that the value changes, then you could just use a computed observable.

Here are both options: http://jsfiddle.net/rniemeyer/tfAGy/

Stacey Thornton

unread,
Feb 16, 2012, 10:02:40 AM2/16/12
to knock...@googlegroups.com
Thanks for the reply! I was trying to accomplish this using a writeable dependantObservable and was not having any kind of luck.

I have not gotten to test it in my server code yet, so I am wondering something. How would this hold up to having a string[] passed into it as a mapped parameter?

The overall idea of this is as follows; I have to make something map to a string[], because that is what the server side code expects (and the viewModel in kind), but I wanted to make it a very simple UI, so I wanted it to work more like typing in stackoverflow's tagging section where it was all handled in a single text field.

I am a bit confused about the ko.computed - what will this do with values that do not come from the binding, but from the existing model before the binding occurs?

Stacey

unread,
Feb 16, 2012, 10:13:20 AM2/16/12
to knock...@googlegroups.com
Here we go, I tried to modify the example a bit to show what I mean. I am trying to use another computed to parse the incoming values for the text box, but that doesn't seem to be working as intended...

<input data-bind="value: computedJoinedValues" />


<hr/>
<ul data-bind="foreach: computedSplitValues">
    <li data-bind="text: $data"></li>
</ul>
 

var ViewModel function({
    this.value ko.observable("");

    //create a separate observableArray and use a subscription to keep it updated
    this.splitValues ko.observableArray([
        "test",
        "test2",
        "test3",
        "test4"
    ]);
    
    this.value.subscribe(function(newValue{
        this.splitValues(newValue.split(","));
    }this);

    //compute the split values from the original observable
    this.computedSplitValues ko.computed(function({
        return this.value().split(",");
    }this);
    
    this.computedJoinedValues ko.computed(function({
        return this.splitValues().join(",");
    }this);
    
};

ko.applyBindings(new ViewModel()); 

rpn

unread,
Feb 16, 2012, 11:16:57 AM2/16/12
to knock...@googlegroups.com
Hi Stacey-
Take a look at this one: http://jsfiddle.net/rniemeyer/tfAGy/1/

So, we can use a writeable computed observable in front of an observableArray.  In the read function we would to join them into a string.  In the write function, we would split them back into an array and update the observableArray.

Hope this helps!

Stacey Thornton

unread,
Feb 17, 2012, 10:06:46 AM2/17/12
to knock...@googlegroups.com
This is absolutely incredible. Thank you so much, this is exactly what I was trying to do. I had no idea that a ko.computed could accomplish something like this with so much simplicity.

I keep forgetting that since KO hit 2.0, the documentation has been a bit updated and I probably could have found this there. I am reading up on the computed thing now and am finding all kinds of interesting uses for it, though I am curious about something. I have an extended question that is beyond the scope of what I asked originally, so I'll understand if it is too much data to question.

on a ko.computed write, the parameter that is passed through it, what determines that? Is that based on just the 'value' of whatever it is bound to? For instance, lets use your (now infamous) jquery ui autocomplete as an example. In the autocomplete, the binding is actually attached to a text box, but it actually holds JSON information. What would happen if you tried to use a ko.computed write with this? Would you get the text in the textbox, or the JSON value?

ko.computed looks like it opens a gateway to things that would have taken rather complicated custom bindings before.

Stacey Thornton

unread,
Feb 17, 2012, 10:12:05 AM2/17/12
to knock...@googlegroups.com
I am noticing that ko.computed actually replaced dependantObservables, but added the native writing support (whereas before, it was kind of confusing to get write support). This is a really good change in my opinion!

rpn

unread,
Feb 17, 2012, 10:47:51 AM2/17/12
to knock...@googlegroups.com
Hi Stacey-
The value that is passed to the writeable computed observable depends on the binding.  The "value" binding sets up a handler for the "change" event and any other events that you list in "valueUpdate".  That handler will pass the value that the user entered to whatever is bound against the binding (an observable, writeable computed observable, or a plain JS property).

So, it is up to the binding, but the general pattern is to listen to an event that involves the user changing data and then deciding how to write that back to the model.  If the write happens to go through a writeable computed observable, then you will have a chance to intercept the value and do whatever you would like to it.

Hope this helps.
Reply all
Reply to author
Forward
0 new messages