knockoutjs单选按钮使用protectedobservable检查值

时间:2014-11-03 23:07:18

标签: javascript jquery html knockout.js

感谢您对此进行调查。

我制作了以下示例:http://jsfiddle.net/zm381qjx/5/

这是一个菜单列表构建器。添加菜单时,会弹出一个编辑表单。使用protectedObservable以便我可以提交或重置(根据代码)。我遇到问题的一个功能是,有单选按钮列表(对于TypeId),并且根据值(10 = Url,20 = Category,30 = Page),您可以设置相应的属性(10 = Url, 20 = CategoryId,30 = PageId)。

点击单选按钮,如果选择了Url,则应显示另一个文本框(基于urlVisible),以便用户可以输入Url。我添加了一个带文本的span:TypeId.temp所以我可以看到临时值。这非常不规律。尝试多次轻弹。

非常感谢任何帮助。

我的HTML

<a class="btn btn-primary" data-bind="click: addMenu">Add Menu</a>
<ul data-bind="foreach: Menus">
    <li><a href="#" data-bind="text: Name, click: editMenu"></a></li>
</ul>
<div class="panel panel-default" data-bind="slideIn: editMenuItem, with: editMenuItem">
    <div class="panel-body">
        <div class="form-group">
            <label for="MenuName">Name: </label>
            <input type="text" id="MenuName" data-bind="value: Name" class="form-control" />
        </div>
        <label class="radio-inline">
            <input type="radio" name="MenuTypeId" value="10" data-bind="checked: TypeId" /> Url
        </label>
        <label class="radio-inline">
            <input type="radio" name="MenuTypeId" value="20" data-bind="checked: TypeId" /> Category
        </label>
        <label class="radio-inline">
            <input type="radio" name="MenuTypeId" value="30" data-bind="checked: TypeId" /> Page
        </label>
        <div class="form-group" data-bind="visible: urlVisible">
            <label for="MenuUrl">Url: </label>
            <input type="text" id="MenuUrl" data-bind="value: Url" class="form-control" />
        </div>
        <br />
        <p>TypeId.temp = <span data-bind="text: TypeId.temp"></span></p>
        <br /><br />
        <input type="button" class="btn btn-success" value="Update" data-bind="click: commit" /> or 
        <a href="#" data-bind="click: reset">Cancel</a>
    </div>
</div>

我的JS:

var vm = null;

//wrapper for an observable that protects value until committed
ko.protectedObservable = function (initialValue) {
    //private variables
    var _temp = ko.observable(initialValue);
    var _actual = ko.observable(initialValue);

    var result = ko.dependentObservable({
        read: function () {
            return _actual();
        },
        write: function (newValue) {
            _temp(newValue);
        }
    });

    //commit the temporary value to our observable, if it is different
    result.commit = function () {
        var temp = _temp();
        if (temp !== _actual()) {
            _actual(temp);
        }
    };

    //notify subscribers to update their value with the original
    result.reset = function () {
        _actual.valueHasMutated();
        _temp(_actual());
    };

    result.temp = _temp;

    return result;
};

ko.bindingHandlers.slideIn = {
    init: function (element) {
        $(element).hide();
    },
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        if (value) {
            $(element).stop().hide().slideDown('fast');
        } else {
            $(element).stop().slideUp('fast');
        }
    }
};

var Menu = function (Id, Name, TypeId, CategoryId, PageId, Url) {
    var self = this;

    /* Core Properties */
    self.Id = ko.observable(Id);
    self.Name = ko.protectedObservable(Name);
    self.TypeId = ko.protectedObservable(TypeId);
    self.CategoryId = ko.protectedObservable(CategoryId);
    self.PageId = ko.protectedObservable(PageId);
    self.Url = ko.protectedObservable(Url);

    /* Virtual Properties */
    self.urlVisible = ko.computed(function () {
        return self.TypeId.temp() == "10";
    }, self);


    /* Virtual Functions */
    self.editMenu = function (data) {
        if(vm.editMenuItem()) {
            vm.editMenuItem(null);
        }
        vm.editMenuItem(data);
    };

    /* Core Functions */
    self.commit = function () {
        if (self.Name.temp() == '' || self.Name.temp() == null) {
            alert('Please enter a name.'); return;
        }

        self.Name.commit();
        self.TypeId.commit();
        self.CategoryId.commit();
        self.PageId.commit();
        self.Url.commit();

        vm.editMenuItem(null);
    };
    self.reset = function () {
        self.Name.reset();
        self.TypeId.reset();
        self.CategoryId.reset();
        self.PageId.reset();
        self.Url.reset();

        vm.editMenuItem(null);
    };
};

var ViewModel = function() {
    var self = this;

    /* Core Properties */
    self.Menus = ko.observableArray([]);

    /* Virtual Properties */
    self.editMenuItem = ko.observable(null);
    self.addMenu = function(){
        var menu = new Menu(0, "New Menu", "10", 0, 0, "");
        self.Menus.push(menu);
        self.editMenuItem(menu);
    };
};


$(function () {
    vm = new ViewModel();
    ko.applyBindings(vm);
});

1 个答案:

答案 0 :(得分:1)

如果您将单选按钮绑定更改为

<input type="radio" name="MenuTypeId" value="10" data-bind="checked: TypeId.temp" />

临时ID将相应更改,单选按钮行为是一致的,但不是TypeId作为值。

还是protectedObservable绑定单选按钮值不好玩

当您手动点击收音机时,TypeId值永远不会改变(因为您没有提交该值),我想由于单选按钮值永远不会从10更改,因此无法识别后续手动点击Url单选按钮

我使用按钮更新了值,并且相应地改变了;但是它不会在随后的单选按钮点击中移动该TypeId的值

问题仍然出现在protectedObservable绑定中,但不是一个简单的observable。

进一步探讨这个想法的代码:http://jsfiddle.net/zm381qjx/101/