Binding Img src attr doesn't update

521 views
Skip to first unread message

cjro...@gmail.com

unread,
Apr 11, 2014, 7:37:22 PM4/11/14
to knock...@googlegroups.com
So, I have a div of images and I use the foreach method of binding the image's src attribute to a the src property of an observablearray.  When I load the page, all images appear perfect.  

From there, the process allows the user to click on an image in the div which sets the chosenImage (which is a ko.observable()) equal to the image clicked.  Within another div that is bound to the chosenImage, the user edits the image.  Then the user clicks a save button which makes an AJAX call within the viewmodel to edit the image.  The AJAX call returns json which I parse and pull the new image url.  I am able to locate the image in the observablearray and edit the src property, but nothing updates.  Within another function that randomly reorders the images in the div, I am able to get the image to refresh.  This function makes a copy/slice of the observablearray into a local variable and then clears out the array.  From there, I loop through the local array to add the images back to the observablearray.  Once this is done processing, all the images refresh properly.

I have tried calling the .valueHasMutated() on the chosenImage, the obserableArray, the selected item in the observablearray, but it doesn't appear to do anything.  What am I missing here?

Any help with this would be greatly appreciated!!

Gunnar Liljas

unread,
Apr 12, 2014, 5:37:54 AM4/12/14
to knock...@googlegroups.com
The src property of the images in the array must be observable too. The reason it works when reordering etc. is that the entire array is rebound.


--
You received this message because you are subscribed to the Google Groups "KnockoutJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email to knockoutjs+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

cjro...@gmail.com

unread,
Apr 12, 2014, 7:31:15 PM4/12/14
to knock...@googlegroups.com
Gunnar - Could you please provide a basic example or point me in the right direction?  

cjro...@gmail.com

unread,
Apr 12, 2014, 11:45:23 PM4/12/14
to knock...@googlegroups.com
Gunnar - This is how I set it my model:

var MyImage = function (_id, _url) {
        this.id = ko.observable(_id);
        this.url = ko.observable(_url);
//...other properties
    }

In my viewmodel I have an observableArray like this (note: I have removed the unnecessary stuff:

var self = this;

self.myImages = ko.observableArray([
          new MyImage(1,'http://www.aWebsite.com/images/aValidImage.jpg'),
]):

....within an event function, I make a GET call using AJAX that returns some JSON with the new URL
//parse the JSON
var newAttr = jQuery.parseJSON(obj.Message);
var currImg;

self.myImages.valueWillMutate();

self.myImages().forEach(function (item) {
      if (item.id == newAttr.id) {
            item.url = newAttr.url;
            
            currImg = item;
      }
});

self.myImages.valueHasMutated();

I tried this, and it's still not working. I have to do this to get it to refresh:

self.myImages.remove(currImg);
self.myImages.push(currImg);

This works, but then my images are no longer in order and the image is appended to the end.  It's a work around, but I am guessing I have something setup wrong and knockout should handle the change.

What am I missing here?

On Saturday, April 12, 2014 5:37:54 AM UTC-4, Gunnar Liljas wrote:

Patrick Steele

unread,
Apr 13, 2014, 9:14:04 AM4/13/14
to knock...@googlegroups.com
This line of code:

this.url = ko.observable(_url);

Defines "url" as a knockout observable.  An observable is actually a function that manages the pub/sub capabilities of knockout.  To get the value of an observable, you must "call" the observable function:

var theUrl = this.url();

Likewise, to set the value of an observable, you need to "execute" the observable and pass it the new value:

this.url(newUrl);

Knowing this, you can see that by setting the url to a new value:

item.url = newAttr.url;

You're just clearing out the reference to the observable and making it a plain javascript string.  Change the code to:

item.url(newAttr.url);

And you should be all set.
Reply all
Reply to author
Forward
0 new messages