1

I have search the interwebs for the last 3 hours looking a solution and have found nothing. The closest I have found to what I am looking for is here: Is it possible to data-bind visible to the negation ("!") of a boolean ViewModel property? . And I haven't been able to get this solution to work.

I am trying to hide a dom element based on a property of a childlistitem of a viewmodel.

    function ViewModel() {
        var self = this;

        this.addSocialMediaLink = function () {
            self.EditProjectSocialMediaViewModels.push({ ProjectId: 0, ProjectSocialMediaId: 0, SocialMediaType: '', Url: '', Deleted: false });

        }.bind(this);

        self.removeSocialMediaLink = function (socialLink) {
            socialLink.Deleted = true;
        }
    }

    $(function () {
        ko.bindingHandlers.hidden = {
            update: function (element, valueAccessor) {
                ko.bindingHandlers.visible.update(element, function () {
                    return !ko.utils.unwrapObservable(valueAccessor());
                });
            }
        };

        var myViewModel = new ViewModel();
        $.getJSON('@Url.Action("GetProject")' + '/ProjectId', null, function (data) {
            ko.mapping.fromJS(data, {}, myViewModel);
            ko.applyBindings(myViewModel);
        });
    });

Server Side VM

public class EditProjectSocialMediaViewModel
{
    public int ProjectId { get; set; }

    public int ProjectSocialMediaId { get; set; }

    [Required]
    [Url]
    [StringLength(100, ErrorMessage = "The {0} must be no longer than 100 characters.")]
    public string Url { get; set; }

    public bool Deleted { get; set; }
}

Dom:

<div data-bind='foreach: EditProjectSocialMediaViewModels'>
    <input type="text" class='required form-control' data-bind='value: Url, hidden: Deleted, attr: { name: "EditProjectSocialMediaViewModels["+$index()+"].Url" }' />
    <a href="#" data-bind="click: $root.removeSocialMediaLink">Delete</a>
    <br />
</div>
<button data-bind='click: addSocialMediaLink'>Add Social Media Link</button>

The value changes and is stored correctly when clicking the link. But visibility does not change.

Community
  • 1
  • 1
Edward
  • 13
  • 2

1 Answers1

1

visibility is not changing because deleted property is not observable, make it observable.

function ViewModel() {
 var self = this;
 self.EditProjectSocialMediaViewModels = ko.observableArray([]);
 this.addSocialMediaLink = function () {
     self.EditProjectSocialMediaViewModels.push({
         ProjectId: 0,
         ProjectSocialMediaId: 0,
         SocialMediaType: '',
         Url: '',
         Deleted: ko.observable(false)
     });

 }.bind(this);

 self.removeSocialMediaLink = function (socialLink) {
     socialLink.Deleted(true);
 }
}

http://jsfiddle.net/U8j5G/

Akhlesh
  • 2,389
  • 1
  • 16
  • 23
  • What about my viewmodel when it is initailially loaded from the server. How do I add the observable(false/true) to it without having to fully reddefine the viewmodel class in javascript. When it is initially loaded, javascript and knockout recognized Deleted as a bool and on initially load the hidden/visible binding from knockout works. If I try to change deleted to ko.observable(true). Get errors about deleted is a bool not a function. – Edward Mar 18 '14 at 12:23
  • ko.mapping.fromJS by default convert each property in observable so you don't need to worry about it. :) – Akhlesh Mar 18 '14 at 12:45
  • its not a problem use ko.mapping to bind your data. – Akhlesh Mar 18 '14 at 12:56
  • That's what I thought. But my initial data coming from the server when I call the delete function on one of the records And update the value visibility doesn't change. ` self.removeSocialMediaLink = function (socialLink) { socialLink.Deleted = true; }` – Edward Mar 18 '14 at 12:58
  • socialLink.Deleted(true) call like this. – Akhlesh Mar 18 '14 at 12:59