Ahmed ilyas
Ahmed ilyas

Reputation: 5822

img attribute, multiple bindings and evaluation not working

KO newbie.

I kinda have this working except that it doesn't quite work!

I want to show the image tag (visible) if the user is logged in (I am using KO with MVC 4 and Razor):

<img id="imgFavRestaurant" data-bind="attr: { style: { visibility: UserId > 0 ? 'visible' : 'hidden' }, src:FavoriteOutletImageUrl }" />

It shows me the right images when the user is logged in however when the user is not logged in, I still see the image tag (but an empty image as I am returning an empty string for the url):

 var userId = 0;
            @if (Site.Web.Helpers.UserContext.IsAuthenticated)
            {
                @:userId = @Site.Web.Helpers.UserContext.User.Id;
            }

            self.UserId = userId;

            self.FavoriteOutletImageUrl = ko.computed(function () 
            { 
                if (userId <= 0)
                {
                    return '';
                }
               return (data.IsUserFavoriteOutlet) ? '@Url.Content("~/Images/FavOutlet.png")' : '@Url.Content("~/Images/NonFavOutlet.png")';
            });

where am I going wrong? Why does it always show the image tag? Also, how do I bind multiple attributes in KO and HTML5?

thank you

Upvotes: 0

Views: 163

Answers (2)

nwayve
nwayve

Reputation: 2331

First, UserId is a plain value and won't update the view unless something forces KO to re-evaluate the binding context that this image element is in. UserId should really be an observable:

self.UserId = ko.observable(userId);

Because the other issue that arises by not doing this is that your FavoriteOutletImageUrl computed won't update because userId isn't an observable, therefore the computed won't care if its value changes. Same with 'data.IsUserFavoriteOutlet'. You'll constantly evaluate this variable and perhaps the user's favorite outlet changes. This should be:

self.IsFavoriteOutlet = ko.observable(data.IsUserFavoriteOutlet);

So your computed would be:

self.FavoriteOutletImageUrl = ko.computed(function () { 
    if (self.UserId() <= 0) {
        return '';
    }

    return self.IsUserFavoriteOutlet()
        ? '@Url.Content("~/Images/FavOutlet.png")'
        : '@Url.Content("~/Images/NonFavOutlet.png")';
 });

Now if the UserId changes or the IsUserFavoriteOutlet changes, this computed will re-evaluate itself.

In your binding, use the KO visible binding instead to show/hide elements.

<img id="imgFavRestaurant" data-bind="visible: UserId > 0 ? 'visible' : 'hidden',
    attr: { src: FavoriteOutletImageUrl }" />

The other thing you should consider is making a computed property to bind with, instead of writing logic in your binding.

self.showRestaurantImage = ko.computed(function(){
    return self.userId() > 0;
});

and:

<img id="imgFavRestaurant" data-bind="visible: showRestaurantImage,
    attr: { src: FavoriteOutletImageUrl }" />

Upvotes: 1

Ahmed ilyas
Ahmed ilyas

Reputation: 5822

I had to do this:

data-bind="style: { visibility: UserId > 0 ? 'visible' : 'hidden' }, attr: { src: FavoriteOutletImageUrl }

Upvotes: 0

Related Questions