【问题标题】:Knockout.js Change (not toggle) css class on clickKnockout.js 单击时更改(不切换)css 类
【发布时间】:2014-09-13 11:03:26
【问题描述】:

我正在尝试在 knockout.js 点击事件上操作 css 类,但它不起作用。目前我正在根据 $data.IsSelected 元素的值(true | false)绑定 css 类。我无法得到正确的方法来做我想做的事 - 我应该使用 DOM 操作(就像我现在尝试做的那样)还是应该将 observableArray 元素的值更改为 true 而不是 false,例如然后更新ViewModel,所以理论上这必须改变 css 类。 这里是 JS。

<script>
        function StyleViewModel() {
            var self = this;
            self.pref = ko.observableArray();
            self.img = ko.observableArray(["img/style1.png", "img/style2.png", "img/style3.png", "img/style4.png", "img/style5.png", "img/style6.png"]);
            self.toggle = function (data, event) {
                if (data.IsSelected == true) {  
                    //Here i'm trying to manipulate with DOM directly                 
                    $(event.target).closest("div").removeClass("txt-active").addClass("txt");
                    $(event.target).find("a.button").text("Добавить");
                }
                else {                 
                    $(event.target).removeClass("txt").addClass("txt-active");
                    $(event.target).find("div.txt-active > a.button").text("Добавлено");
                }
            }
            $.getJSON('/api/usersprofiles?userguid=' + $("#MainContent_guid").val(), self.pref);
        }
        $(document).ready(function () {
            ko.applyBindings(new StyleViewModel());
            $("#go").click(function () {
                $("div.test-block").each(function () {
                    var style = $(this).find("h3").text();
                    var option = $(this).find("a").text();
                    var selected;
                    if (option == "Добавить") {
                        selected = false;
                    }
                    else if (option == "Добавлено") {
                        selected = true;
                    }
                    var json = "{'UserGUID':'" + $("#MainContent_guid").val() + "', 'Style':'" + style + "', 'Selected':'" + selected + "'}"
                    $.ajax({
                        type: "POST",
                        dataType: "json",
                        contentType: 'application/json; charset=utf-8',
                        url: "/api/usersprofiles",
                        data: json,
                        success: function () { },
                        error: function (xhr, status, error) {
                            var err = eval("(" + xhr.responseText + ")");
                            alert(err.Message);
                        }
                    });
                });
                setTimeout(function () {
                    window.location.replace("default.aspx");
                }, 3000);
            });
        });
    </script>

这是显示绑定的 HTML:

<input type="hidden" runat="server" id="guid" />
    <div class="container">
        <div class="title">
            <h2>Вкусы</h2>
            <p>Что вам по душе?</p>
        </div>
        <div class="styles" data-bind="foreach: pref">
            <div class="test-block" data-bind="click: $root.toggle">
                <input type="hidden" data-bind="value: $data.Id" />
                <div class="bigshadowtest">
                    <img alt="" src="img/bigshadow.png">
                </div>
                <div data-bind="css: $data.IsSelected == true ? 'txt-active' : 'txt'">
                    <h3 data-bind="text: $data.name"></h3>
                    <a href="#" class="button" data-bind="text: $data.IsSelected == true ? 'Добавлено' : 'Добавить'"></a>
                </div>
                <img alt="" data-bind="attr: { src: $root.img }">
            </div>
        </div>
        <table class="info" style="width: 100%; height: 100%;">
            <tr>
                <td style="text-align: center; vertical-align: middle;">
                    <a href="#" id="go" class="gobtn">Поехали!</a>
                </td>
            </tr>
        </table>
    </div>

附:这里还有一个问题 - 我无法将 observableArray self.img 绑定到相应的 img 元素。

【问题讨论】:

  • IsSelected 是可观察的吗?我看不到它的值在哪里根据选择而改变?我认为您希望在单击 div 时更改它,因此在切换功能中只需切换选定的值,绑定将完成它们的工作,因为 IsSelected 是一个可观察的。
  • 不,IsSelected 是 observableArray 中的元素之一。例如:{"$id":"1","name":"Стритстайл","IsSelected":true} @manji,你能用一些代码解释一下你的意思吗?
  • 看看这个plunkr。至于图像, src 属性需要一个字符串,但您提供的是 observableArray。您可能希望根据首选项分配图像,因此请使用包含当前 foreach 循环索引的淘汰赛$index observbale(已在 plunkr 中完成)。

标签: javascript jquery html css knockout.js


【解决方案1】:

使您的可观察数组的元素可观察。使用mapping plugin,这样您的 isSelected 将是一个 observable 并将其值更改反映到 ui。

更改您的 getJson 方法(未经测试的代码)


$.getJSON('/api/usersprofiles?userguid=' + $("#MainContent_guid").val(), function(data) {
    ko.mapping.fromJS(data, self.pref);
});

或者不使用映射插件,你可以创建一个新的 pref 对象并将数据从服务器绑定到循环中,然后将它们推送到 observableArray。这种方式比使用映射插件更可控。

    var oPref = function (data) {
        var self = this;

        self.Id = ko.observable(data.Id);
        self.IsSelected = ko.observable(data.IsSelected);
        self.name = ko.observable(data.name);
        self.imgLink = ko.observable(data.imgLink);

        self.toggle = function () {
            if (self.IsSelected()) self.IsSelected(false);
            else self.IsSelected(true);
        }
    }

        function StyleViewModel() {
            var dataFromServer = [ 
                { Id: 1, IsSelected: false, name: "name1", imgLink: "img/style1.png" },
                { Id: 2, IsSelected: false, name: "name2", imgLink: "img/style2.png" },
                 { Id: 3, IsSelected: false, name: "name3", imgLink: "img/style3.png" }]

            var self = this;

            self.pref = ko.observableArray();

            ko.utils.arrayForEach(dataFromServer, function(item) { self.pref.push(new oPref(item)); });
        }
    $(document).ready(function () {
        ko.applyBindings(new StyleViewModel());
    });

您的 html 应该如下所示

<input type="hidden" runat="server" id="guid" />
<div class="container">
    <div class="title">
         <h2>Вкусы</h2>

        <p>Что вам по душе?</p>
    </div>
    <div class="styles" data-bind="foreach: pref">
        <div class="test-block" data-bind="click: toggle">
            <input type="hidden" data-bind="value: Id" />
            <div class="bigshadowtest">
                <img alt="" src="img/bigshadow.png">
            </div>
            <div data-bind="css: { 'txt-active': IsSelected(), 'txt': IsSelected() == false }">
                 <h3 data-bind="text: name"></h3>
 <a href="#" class="button" data-bind="text: (IsSelected() == true ? 'Добавлено' : 'Добавить')"></a>

            </div>
            <img alt="" data-bind="attr: { src: imgLink }">
        </div>
    </div>
    <table class="info" style="width: 100%; height: 100%;">
        <tr>
            <td style="text-align: center; vertical-align: middle;"> <a href="#" id="go" class="gobtn">Поехали!</a>

            </td>
        </tr>
    </table>
</div>

【讨论】:

  • 你能举个例子吗?
  • 请注意,如果您将 IsSelected 设为 observable。由于 $data.IsSelected 是一个函数,$data.IsSelected == true 将不起作用。你应该改用 $data.IsSelected() == true 。
  • 感谢您提供完整的示例。我怕你误会了。这个值(真或假)是我第一次真正从服务器获取,但是当我更改 css 类时,我只是将其更改为相反的值,例如if (data.IsSelected == true) { 将元素设置为 false }。
  • @andrey.shedko 如果您可以使 isSelected 可观察,并且在切换功能中只需更改 isSelected 的值,如 data.IsSelected(false); css 也会根据你在 ui 上定义的规则发生变化。
猜你喜欢
  • 2012-06-29
  • 2021-08-10
  • 2016-09-30
  • 1970-01-01
  • 1970-01-01
  • 2018-09-27
  • 2016-08-27
  • 2017-10-29
  • 1970-01-01
相关资源
最近更新 更多