I’m currently working on a web application where I have to write an interface that allows users to delete photos that they have uploaded to the site. The user interface and corresponding view model are based on the following design.
So, we have a collection of photo urls stored in an observable array of strings. By way of a foreach binding we create an image for each url which can be selected by clicking on it. Clicking on the delete button deletes the currently selected image, which works by removing it from the observable array and unselecting it.
Except that the code as it is written above doesn’t work. When we attempt to delete an image, the url is not correctly removed from the observable collection.
The reason for this is quite interesting.
remove() works by searching the observable array for any members that are exactly equal to the argument passed to the method and removing them. Notice how I said exactly equals? Herein lies our problem. If we select the photo with the src attribute set to
url0 and then examine the value of
What we have here is an instance of the
String class. This is not the same thing as the
String object using the “strict equal” operator (
===), the comparison returns false. This is the comparison that
So how do we get around this? Well, if we set
self.selected in the
data-bind attribute using an inline function instead of in the view model, the string primitive is stored in the variable and not the object. This isn’t a very good solution however, because it requires us to scatter our view model logic throughout the HTML page. A better way to accomplish this is to call
this when we are setting the
valueOf() obtains the primitive value from the
String class, and setting this as our selected photo url will ensure that we can remove it from the observable array when we need to.
valueOf() is also a good choice because it works for all class/primitive type pairs, not just with
string. This is important because we get the same behaviour when working with arrays of numbers or bools as well.