injecting observables & views

63 views
Skip to first unread message

sag...@gmail.com

unread,
Apr 5, 2012, 5:56:39 PM4/5/12
to knock...@googlegroups.com
Hi, I am trying to generate observables and matching views on the fly, but somehow this does not work.
In the model constructor:

    self.stats = ko.observableArray();

In a handler that gets called much later:

    evnt = {name:"average", value:"33.22"}; // this is actually coming from an ajax call
    ...
    self.stats[evnt.name] = new ko.observable(evnt.value);
    $('#stats').append( '<div>'+ evnt.name +': <span data-bind="text: stats[\'' + evnt.name + '\']"></span></div>');

Hard to jsfiddle that due to the late update...

Any suggestion?


jason.s...@gmail.com

unread,
Apr 5, 2012, 6:15:20 PM4/5/12
to knock...@googlegroups.com
I'm pretty new to KO, so my guess would be:
self.stats()[evnt.name].value(evnt.value);

the () are needed to bring back the collection or value... kind of like .val() in jquery.

if that wild guess doesn't work then try this:

var stat = self.stats().filter(function(stat){
return stat.name === evnt.name;
}
stat.value(evnt.value);

hope those work for you!

jason.s...@gmail.com

unread,
Apr 5, 2012, 6:16:40 PM4/5/12
to knock...@googlegroups.com
of course I have syntax issues in the filter example as I typed it in this reply editor...


On Thursday, April 5, 2012 5:56:39 PM UTC-4, sag...@gmail.com wrote:

sag...@gmail.com

unread,
Apr 6, 2012, 4:00:38 AM4/6/12
to knock...@googlegroups.com
Thanks Werewolf. This does not solve the problem.

Note that the same code works when I am using it 'statically', meaning if I hard-code the observable & the html view instead of creating it dynamically.

Sagi

Matthew Schinckel

unread,
Apr 6, 2012, 6:00:59 AM4/6/12
to knock...@googlegroups.com
Can you try putting the update in a setTimeout(), just to get the fiddle working?

Off-hand, I'd suspect that the $().append() is adding something to the DOM, but I'm not sure if KO will notice that the added element has a data-bind attribute and use it.

Perhaps you could re-word the addition so that it is done using a KO if: statement? 

Matt.

sag...@gmail.com

unread,
Apr 6, 2012, 6:21:59 AM4/6/12
to knock...@googlegroups.com
Now with a jsfiddle demonstrating the problem:


Sagi

Carsten Senger

unread,
Apr 6, 2012, 10:40:05 AM4/6/12
to knock...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Sagi,

Am 06.04.2012 12:21, schrieb sag...@gmail.com:
> Now with a jsfiddle demonstrating the problem:
>
> http://jsfiddle.net/2LWUn/12/

An observableArray is an array (like in 'a list'), not a javascript
object (assoziative array).

http://knockoutjs.com/documentation/observableArrays.html

You can push to the observableArray to update it. (You do not get an
error cause it is also a javascript object, but the properties are not
the observables).

Here is an updated fiddle:

http://jsfiddle.net/5syVA/1/

You might want to look at the mapping plugin if you want to
construct/update objects with observable properties from json.

http://knockoutjs.com/documentation/plugins-mapping.html


Cheers,

..Carsten

> On Friday, April 6, 2012 11:00:38 AM UTC+3, sag...@gmail.com
> wrote:
>
> Thanks Werewolf. This does not solve the problem.
>
> Note that the same code works when I am using it 'statically',
> meaning if I hard-code the observable & the html view instead of
> creating it dynamically.
>
> Sagi
>
> On Friday, April 6, 2012 1:16:40 AM UTC+3, Werewolf wrote:
>
> of course I have syntax issues in the filter example as I typed it
> in this reply editor...
>
> On Thursday, April 5, 2012 5:56:39 PM UTC-4, sag...@gmail.com
> wrote:
>
> Hi, I am trying to generate observables and matching views on the
> fly, but somehow this does not work. In the model constructor:
>
> self.stats = ko.observableArray();
>
> In a handler that gets called much later:
>
> evnt = {name:"average", value:"33.22"}; // this is actually coming

> from an ajax call ... self.stats[evnt.name <http://evnt.name>] =


> new ko.observable(evnt.value); $('#stats').append( '<div>'+

> evnt.name <http://evnt.name> +': <span data-bind="text: stats[\''
> + evnt.name <http://evnt.name> + '\']"></span></div>');


>
> Hard to jsfiddle that due to the late update...
>
> Any suggestion?
>
>
>
> On Friday, April 6, 2012 11:00:38 AM UTC+3, sag...@gmail.com
> wrote:
>
> Thanks Werewolf. This does not solve the problem.
>
> Note that the same code works when I am using it 'statically',
> meaning if I hard-code the observable & the html view instead of
> creating it dynamically.
>
> Sagi
>
> On Friday, April 6, 2012 1:16:40 AM UTC+3, Werewolf wrote:
>
> of course I have syntax issues in the filter example as I typed it
> in this reply editor...
>
> On Thursday, April 5, 2012 5:56:39 PM UTC-4, sag...@gmail.com
> wrote:
>
> Hi, I am trying to generate observables and matching views on the
> fly, but somehow this does not work. In the model constructor:
>
> self.stats = ko.observableArray();
>
> In a handler that gets called much later:
>
> evnt = {name:"average", value:"33.22"}; // this is actually coming

> from an ajax call ... self.stats[evnt.name <http://evnt.name>] =


> new ko.observable(evnt.value); $('#stats').append( '<div>'+

> evnt.name <http://evnt.name> +': <span data-bind="text: stats[\''
> + evnt.name <http://evnt.name> + '\']"></span></div>');


>
> Hard to jsfiddle that due to the late update...
>
> Any suggestion?
>
>

- --
Carsten Senger - Schumannstr. 38 - 65193 Wiesbaden
sen...@rehfisch.de - (0611) 5324176
PGP: gpg --recv-keys --keyserver hkp://subkeys.pgp.net 0xE374C75A
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iQEcBAEBAgAGBQJPfwBFAAoJEAOSv+HjdMdayD8IANYc7E85ufLxcGLxg4lJPjHc
Mq0uZ1NnamhZO3wWUoE6QyLWGA41pDJU/j9ywPalTAkCTET2JFjJFiU8rvswReRQ
hytHBB9LsG2oA6IO0+t7nCtezn1S5nJWO++vUGRn/JaMnfWb801lawTsF/PmkL1H
2H2PB9UgDNsl+XI3g/QHwxPRfu6MjKiRomF5Wb6EKxy3+vxhhtDDGcjj383n25cG
NxuzYvIc6+yHnyYgJJwiSXIfPHbqZBlrdA141MdUR5yWYnfXJtpEGXLJ4NfQ3bIc
bxCl0IgjkPPk61znVkvZlPPjaEQ9ZOKbJnLqqruSsH3I0rg393mhlGuREL5vQac=
=Ef0B
-----END PGP SIGNATURE-----

sag...@gmail.com

unread,
Apr 7, 2012, 1:22:53 PM4/7/12
to knock...@googlegroups.com
Thanks Carsten. I understand.

However, even when I'm using an observable, I don't see updates (see  http://jsfiddle.net/2LWUn/15/ ).

In your jsfiddle, I am getting a new line with each update, which is not what I need - These are essentially counters I am displaying, and their content should update (see  http://jsfiddle.net/c27NB/4/  for a non-knockout implementation which achieves what I need).

My preference would be to avoid bypassing knockout to implement this. I'm pretty sure there's a way.

Cheers,

Sagi


On Friday, April 6, 2012 5:40:05 PM UTC+3, Carsten Senger wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Sagi,

Am 06.04.2012 12:21, xxxxx


> Now with a jsfiddle demonstrating the problem:
>
> http://jsfiddle.net/2LWUn/12/

An observableArray is an array (like in 'a list'), not a javascript
object (assoziative array).

http://knockoutjs.com/documentation/observableArrays.html

You can push to the observableArray to update it. (You do not get an
error cause it is also a javascript object, but the properties are not
the observables).

Here is an updated fiddle:

http://jsfiddle.net/5syVA/1/

You might want to look at the mapping plugin if you want to
construct/update objects with observable properties from json.

http://knockoutjs.com/documentation/plugins-mapping.html


Cheers,

..Carsten

> On Friday, April 6, 2012 11:00:38 AM UTC+3, xxxx


> wrote:
>
> Thanks Werewolf. This does not solve the problem.
>
> Note that the same code works when I am using it 'statically',
> meaning if I hard-code the observable & the html view instead of
> creating it dynamically.
>
> Sagi
>
> On Friday, April 6, 2012 1:16:40 AM UTC+3, Werewolf wrote:
>
> of course I have syntax issues in the filter example as I typed it
> in this reply editor...
>

> On Thursday, April 5, 2012 5:56:39 PM UTC-4, xxx


> wrote:
>
> Hi, I am trying to generate observables and matching views on the
> fly, but somehow this does not work. In the model constructor:
>
> self.stats = ko.observableArray();
>
> In a handler that gets called much later:
>
> evnt = {name:"average", value:"33.22"}; // this is actually coming
> from an ajax call ... self.stats[evnt.name <http://evnt.name>] =
> new ko.observable(evnt.value); $('#stats').append( '<div>'+
> evnt.name <http://evnt.name> +': <span data-bind="text: stats[\''
> + evnt.name <http://evnt.name> + '\']"></span></div>');
>
> Hard to jsfiddle that due to the late update...
>
> Any suggestion?
>
>
>

> On Friday, April 6, 2012 11:00:38 AM UTC+3, xxxx


> wrote:
>
> Thanks Werewolf. This does not solve the problem.
>
> Note that the same code works when I am using it 'statically',
> meaning if I hard-code the observable & the html view instead of
> creating it dynamically.
>
> Sagi
>
> On Friday, April 6, 2012 1:16:40 AM UTC+3, Werewolf wrote:
>
> of course I have syntax issues in the filter example as I typed it
> in this reply editor...
>

> On Thursday, April 5, 2012 5:56:39 PM UTC-4, xxxx


> wrote:
>
> Hi, I am trying to generate observables and matching views on the
> fly, but somehow this does not work. In the model constructor:
>
> self.stats = ko.observableArray();
>
> In a handler that gets called much later:
>
> evnt = {name:"average", value:"33.22"}; // this is actually coming
> from an ajax call ... self.stats[evnt.name <http://evnt.name>] =
> new ko.observable(evnt.value); $('#stats').append( '<div>'+
> evnt.name <http://evnt.name> +': <span data-bind="text: stats[\''
> + evnt.name <http://evnt.name> + '\']"></span></div>');
>
> Hard to jsfiddle that due to the late update...
>
> Any suggestion?
>
>

- --
Carsten Senger - 

xxxx - (0611) 5324176


PGP: gpg --recv-keys --keyserver hkp://subkeys.pgp.net 0xE374C75A
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

Carsten Senger

unread,
Apr 7, 2012, 4:36:23 PM4/7/12
to knock...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 07.04.2012 19:22, schrieb sag...@gmail.com:
> Thanks Carsten. I understand.
>
> However, even when I'm using an observable, I don't see updates
> (see http://jsfiddle.net/2LWUn/15/ ).
>
> In your jsfiddle, I am getting a new line with each update, which
> is not what I need - These are essentially counters I am
> displaying, and their content should update (see
> http://jsfiddle.net/c27NB/4/ for a non-knockout implementation
> which achieves what I need).

Yep, I used the observableArray which is not a good choice if you just
want to update one property.

> My preference would be to avoid bypassing knockout to implement
> this. I'm pretty sure there's a way.

The simplest way is to use a ko.observable() property that you update.
Knockout won't look "inside" the object you initialized the self.stats
observable with so you don't see any changes in your fiddle.

I changed it to show two possible ways, using simple ko.observable()s
or the mapping plugin. If you have several stats values delivered as a
json response the mapping plugin is very convenient. For one or two
values I'd use simple properties.

http://jsfiddle.net/fDeWC/1/


Cheers,

..Carsten

>> evnt.name <http://evnt.name> <http://evnt.name> +': <span
> data-bind="text: stats[\''
>> + evnt.name <http://evnt.name> <http://evnt.name> +


> '\']"></span></div>');
>
>> Hard to jsfiddle that due to the late update...
>
>> Any suggestion?
>
>
>
>> On Friday, April 6, 2012 11:00:38 AM UTC+3, xxxx wrote:
>
>> Thanks Werewolf. This does not solve the problem.
>
>> Note that the same code works when I am using it 'statically',
>> meaning if I hard-code the observable & the html view instead of
>> creating it dynamically.
>
>> Sagi
>
>> On Friday, April 6, 2012 1:16:40 AM UTC+3, Werewolf wrote:
>
>> of course I have syntax issues in the filter example as I typed
>> it in this reply editor...
>
>> On Thursday, April 5, 2012 5:56:39 PM UTC-4, xxxx wrote:
>
>> Hi, I am trying to generate observables and matching views on
>> the fly, but somehow this does not work. In the model
>> constructor:
>
>> self.stats = ko.observableArray();
>
>> In a handler that gets called much later:
>
>> evnt = {name:"average", value:"33.22"}; // this is actually
>> coming from an ajax call ... self.stats[evnt.name
>> <http://evnt.name>

> <http://evnt.name>] =
>> new ko.observable(evnt.value); $('#stats').append( '<div>'+

>> evnt.name <http://evnt.name> <http://evnt.name> +': <span
> data-bind="text: stats[\''
>> + evnt.name <http://evnt.name> <http://evnt.name> +


> '\']"></span></div>');
>
>> Hard to jsfiddle that due to the late update...
>
>> Any suggestion?
>
>
>
>

- --

Carsten Senger - Schumannstr. 38 - 65193 Wiesbaden

sen...@rehfisch.de - (0611) 5324176


PGP: gpg --recv-keys --keyserver hkp://subkeys.pgp.net 0xE374C75A
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iQEcBAEBAgAGBQJPgKVHAAoJEAOSv+HjdMdaPG8H/i+pZgY8FIlyArXMxJ4t+/Ay
r/HSjB0g1KGK33uttTWp+8e7jRKKLy3zTqJVFH/FtRS+5J7gqMBo8nPvonYkPvUN
ZvwLDI4/bAqgvefEc6lJ4re0JZifUDRJ8Vc56Y9GIYso9DLn7jb5tl//zS95W7aZ
am8sG4Z+fRY8T3kQOU8UR13uf+Y+L+8T11uxWjepES/MJrHi6zQvDQ0ynCi3oQ+q
MeudoMOSw8vtroWImflXH552oEGa2n7iKB9nXUpf+zx3KxVfYjCbeTYTI76YpaAc
8IpFjbA7WrkKsMRVDp/jjB5psuj+VIBmcQKa1p4ZBrzwua1O2YIZRULne/D4pzE=
=nQIU
-----END PGP SIGNATURE-----

sag...@gmail.com

unread,
Apr 8, 2012, 2:52:06 AM4/8/12
to knock...@googlegroups.com
Hi Carsten, in all your examples, "average" is hard-coded in the view (in html) and in the model (js).

My challenge is that these need to be dynamic, so tomorrow, the json feed can include a new stat ("max"?) and therefore I cannot hardcode things. 

If you look at my knockout-less example, (http://jsfiddle.net/c27NB/5/) you will see that when I see a new stat name, I inject a new div, and when I get an updated value for a stat, I am pushing the value into the div by manipulating the DOM directly, which I'd rather not do if I can find a way to do it within knockout.

http://jsfiddle.net/2LWUn/16/ seems to me like a straightforward binding in knockout, it just doesn't seem to work due to the late creation on the view, which is what I'm trying to address.

Sagi

On Saturday, April 7, 2012 11:36:23 PM UTC+3, Carsten Senger wrote:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Am 07.04.2012 19:22, schrieb

Carsten Senger

unread,
Apr 10, 2012, 3:12:58 PM4/10/12
to knock...@googlegroups.com
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hi Sagi,

Am 08.04.2012 08:52, schrieb sag...@gmail.com:
> Hi Carsten, in all your examples, "average" is hard-coded in the
> view (in html) and in the model (js).
>
> My challenge is that these need to be dynamic, so tomorrow, the
> json feed can include a new stat ("max"?) and therefore I cannot
> hardcode things.
>
> If you look at my knockout-less example,
> (http://jsfiddle.net/c27NB/5/) you will see that when I see a new
> stat name, I inject a new div, and when I get an updated value for
> a stat, I am pushing the value into the div by manipulating the DOM
> directly, which I'd rather not do if I can find a way to do it
> within knockout.
>
> http://jsfiddle.net/2LWUn/16/ seems to me like a straightforward
> binding in knockout, it just doesn't seem to work due to the late
> creation on the view, which is what I'm trying to address.


I don't know of a way to inject single observables on the fly after
you have bound the dom to a model.

You can use the observableArray with a data structure you used in your
fiddle and do a little more work than I did in
http://jsfiddle.net/5syVA/1/ (Read: replacing the right objects in the
array, don't just push to the end).


..Carsten

> <http://evnt.name> +
>> '\']"></span></div>');
>
>>> Hard to jsfiddle that due to the late update...
>
>>> Any suggestion?
>
>
>
>
>
>

- --
Carsten Senger - Schumannstr. 38 - 65193 Wiesbaden
sen...@rehfisch.de - (0611) 5324176
PGP: gpg --recv-keys --keyserver hkp://subkeys.pgp.net 0xE374C75A
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iQEcBAEBAgAGBQJPhIY6AAoJEAOSv+HjdMdaQ1MIAK5OZ1bohMZrIy57Gk+oyUH6
Rn0K+CoUD0OuC+Zv6F7AZR64lMuqo0QTkkgsOU3dDVP14GvSsXqCX8T6F/7E2gpJ
4pbe1ho3DEC91LO3Emz3yaBVCjaynrnmtbh5wz8wFkNicL61Y5K+U60cXJCRCQml
ZWSaXzy2JnO36XWrwgZoGq3JmIxu4fcXuNuP4BUwcYDBGW1aEsFuq40cej1+AR+d
2gl2DuN7YeKdJoRlfgbpbbs5tccZhHh2vmBVvg0GzzGlJD9+7hJU4V/rz4PiAMCD
sQ78srb3RYViEBmetal4NJ4PZ3un4p2LHmvSCiG1B3+E1gQlKn1vx1hHqSSj/AA=
=ZsMu
-----END PGP SIGNATURE-----

Reply all
Reply to author
Forward
0 new messages