如何正确引用传递给knockout.JS的当前元素的属性?

时间:2012-09-12 15:59:22

标签: javascript jquery knockout.js

处理一些反馈表,我是Knockout / jQuery游戏的新手,所以我确定这是一个语法错误。

目标/背景

  • 我有一份反馈表,其中一部分包含一个包含反馈类型的列表。我想要使​​用的反馈类型的实际文本存储在LI标签的“Title”属性中。
  • 我想从一组表示反馈类型的LI标签中传递onclick。
  • 我想要敲门来接收带有调用元素
  • 的onclick事件
  • 我希望ViewModel函数根据LI标题属性的内容更新ViewModel的反馈类型
  • 然后,我想从所有列表中删除一个类,并将其应用于所选元素。
    • 我已经有jQuery这样做了;只想将其纳入模型变更中。

我到目前为止

HTML反馈表(UL列表)的相关部分:

        <ul class="thumbnails" id="feedbackList">
            <li class="feedbackItem" id="feedbackItemPraise" title="Praise" data-bind="click: updateFeedbackType"><i class="icon-thumbs-up"></i>Praise</li>
            <li class="feedbackItem" id="feedbackItemCriticism" title="Criticism" data-bind="click: updateFeedbackType"><i class="icon-thumbs-down"></i>Criticism</li>
            <li class="feedbackItem" id="feedbackItemProblem" title="Problem" data-bind="click: updateFeedbackType"><i class="icon-warning-sign"></i>Problem</li>
            <li class="feedbackItem" id="feedbackItemQuestion" title="Question" data-bind="click: updateFeedbackType"><i class="icon-question-sign"></i>Question</li>
        </ul>

到目前为止的ViewModel(包括一些不相关的部分):

var FeedbackViewModel = function () {
    var self = this;
    self.manualEMailAddress = "MyEmail@MyProvider.com";
    self.manualApplicationName = "MyApplication";
    self.username = ko.observable($("#feedbackUsernameFromServer").val());
    self.feedbackType = ko.observable("Praise");
    self.wantsFollowUp = ko.observable(true);
    self.enteredName = ko.observable("");
    self.feedbackText = ko.observable("");
    self.userNameCaptured = ko.computed(function () { return self.username().length > 3; }, self);
    self.mailToLink = ko.computed(function () { return "mailto:" + self.manualEMailAddress + "?subject=" + encodeURIComponent(self.feedbackType()) + encodeURIComponent(" for ") + encodeURIComponent(self.manualApplicationName) + "&body=" + encodeURIComponent(self.feedbackText()) }, self);
};

var feedbackViewModel = new FeedbackViewModel();

ko.applyBindings(feedbackViewModel, document.getElementById("feedbackModal"));

当前用于更改样式的jQuery(尚未链接到模型):

$("#feedbackList li").click(function () {
    $("#feedbackList li.feedbackItem-Highlighted").removeClass("feedbackItem-Highlighted");
    $(this).addClass("feedbackItem-Highlighted");
});

我认为我需要添加到ViewModel中,但不能正常工作:

self.updateFeedbackType = function (elementToChangeTo) {
    self.feedbackType($(elementToChangeTo).attr("title"));
    $("#feedbackList li.feedbackItem-Highlighted").removeClass("feedbackItem-Highlighted");
    $(elementToChangeTo).addClass("feedbackItem-Highlighted");
};

这导致feedbackType变为未定义且未发生视觉变化。

我哪里错了?谢谢你的帮助!

2 个答案:

答案 0 :(得分:2)

我认为你只需要在vm的定义中使用该功能。

这是一个似乎有用的jsfiddle:

http://jsfiddle.net/gN3HV/

更新:这是一个更好地利用淘汰赛并正确实现目标的小提琴:

http://jsfiddle.net/gN3HV/7/

答案 1 :(得分:1)

elementToChangeTo返回FeedbackViewModel(与this相同)而不是点击的元素 - 行为与jQuery略有不同。

传递给updateFeedbackType的第二个参数将是一个事件,因此您可以使用$(event.target)来获取对被点击元素的引用。

self.updateFeedbackType = function (view, event) {
    var $elementToChangeTo = $(event.target);
    self.feedbackType($elementToChangeTo.attr("title"));
    $("#feedbackList li.feedbackItem-Highlighted").removeClass("feedbackItem-Highlighted");
    $elementToChangeTo.addClass("feedbackItem-Highlighted");
};

然而,@ daedalus28已经解决了更大的问题,即你没有利用knockout.js的优势,并且使这个过程过于复杂。你真的不需要两者来解决这种简单的条件。