【问题标题】:Knockout.js - Set an attribute on drop-down without permanently binding to modelKnockout.js - 在下拉列表中设置属性而不永久绑定到模型
【发布时间】:2015-01-30 06:16:29
【问题描述】:

我想我有一个非常笼统的问题,但它是针对特定应用程序的。我只是想知道如何在下拉列表上设置一个等于下拉列表初始值的自定义属性。该值将从 KnockOut 视图模型值绑定,但我不想让它永久绑定,因此如果它更改,该属性的值不会更改:

<select data-bind="options: availableSlots, attr: { preset: SlotPosition }, event: {'change', myChangeRoutine} " ></select> 

在上面的示例中,preset 是我的属性,我想将其设置为 SlotPosition,它位于我的视图模型中,并且下拉列表最初会自动设置为。 availableSlots 是一个 MVC 服务器端创建的 SelectListItem,它具有插槽 1 到 x 个我作为 ko.observableArray() 返回到我的视图模型中的项目。 (在服务器端代码中,我将 Selected 设置为 true,在需要为给定值设置的位置,并构建选项。)

上面的示例将我的属性preset 绑定到我的模型值SlotPosition,但我只想让它记住该值直到它被更改,而不是永久绑定到它。我遇到的问题是,在myChangeRoutine 中,preset 的值已经成为下拉列表更改为的值。我希望它能够工作,以便当我更改下拉列表的值并运行 myChangeRoutine 时,我可以使用旧值做一些事情。

【问题讨论】:

  • 我希望你在这里看到的是小提琴链接 jsfiddle.net/supercool/74dh736s/11
  • 我想是的。我将其修改为 jsfiddle.net/navyjax2/Ls5aw9xs 以匹配我在代码中尝试执行的操作。但是由于某种原因,即使它使用您的基线在那里工作,它仍然会将新值设置为 self.SlotPosition() myChangeRoutine 在我的实际代码中运行时。所以我按照 Max 建议的方式进行 - 请参阅我的最终代码 jsfiddle.net/navyjax2/7kkuwsLa
  • vapcguy 你可以以更好的方式(更清洁的方式)实现这一点。检查发布的答案。 MaxBrodin 提到 peek() 确实很有用,但在你的情况下,有更好的替代方案来减少代码。

标签: javascript asp.net-mvc knockout.js custom-attributes dropdownbox


【解决方案1】:

只需将您的SlotPosition 设为简单的普通值,而不是ko.observable,这将是一次绑定。 或者使用attr { preset : SlotPosition.peek() },见documentation

【讨论】:

  • 不幸的是,不能将其设为普通值,因为我必须将位置保存回数据库。您是否建议向未绑定到数据库的视图模型添加一个常量?试过了 - 我仍然必须将其初始化为 self.SlotPosition - 它仍然将其设置为新值。我尝试按照您的建议设置.peek() inline,但它仍然将预设设置为新值而不是保留旧值。
  • 实际上,我正在初始化添加到视图模型中的常量 self.Presetself.SlotPosition,而我应该将它初始化为 self.SlotPosition.peek(),正如您正确建议的那样。这行得通!非常感谢!
  • 因此,对于将来发现此问题的任何人,总结一下什么是有效的,我在下拉列表中的data-bind 上使用了attr { preset : Preset },在我的视图模型中使用了self.Preset = self.SlotPosition.peek()
【解决方案2】:

这可以通过更简单的方式实现,不需要任何更改事件和其他使视图变得复杂的东西。我们只需要使用subscribe

查看模型:

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

    self.availableSlots = ko.observableArray(slots);   
    self.Id = '999';
    self.SlotPosition = ko.observable();    
    self.Preset = ko.observable(1); 

     self.SlotPosition.subscribe(function(newVal){
         if(newVal == self.Preset()) return false;
         var newVal = self.SlotPosition(); 
         alert('newVal: ' + newVal);
         alert('oldVal: ' + self.Preset());
         // Then, I find my other dropdown from the next model 
         // using the newVal, and set it to oldVal
         // After doing you work set the newVal to self.Preset
         self.Preset(newVal); 
    });

};
ko.applyBindings( new ViewModel() );

查看:

<div>
    <select data-bind="options: slots, optionsText: 'Text', optionsValue: 'Value', value: SlotPosition"> </select>
</div>

无需窥视工作小提琴使用订阅 here

使用订阅 peek 工作小提琴 here

【讨论】:

  • 赞!当我有一个更改事件和函数时,看起来你拥有的是 .subscribe()。我认为这是一个偏好问题。不幸的是,这个想法是插槽可以是任何数字 - 而不是“1”,所以我无法将“Preset”预设为“1”,就像你在“Without peek”中所做的那样。最初,该值必须等于.SlotPosition,所以我不得不使用.peek(),或者因为这对我来说最终是错误的,所以我在初始加载时遍历了所有下拉列表并用JavaScript手动填充preset从下拉值。也许有不同的方式,但是当你工作到很晚时......
  • 我喜欢你如何使用模型来设置值,而不是我使用 JavaScript 获取/设置属性...只是发现我不能在我的实现中依赖它,因为对象直到最后才会保存。
  • 所需要的只是一个条件。检查这个(jsfiddle.net/supercool/7kkuwsLa/6),不要偷看,也不要将静态数字传递给 observables 。关于评论 2 好 ko 像那样工作(视图模型将与视图同步)。这里的一件事不要将 ko 与 jquery 混淆(主要但并非总是如此)。 ko 中有很多选项可以完成您的工作。欢呼
猜你喜欢
  • 2013-07-01
  • 2013-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多