Knockout:在改变可观察数组后设置select的标题

Knockout: Set caption of select after changing observable array

本文关键字:设置 select 标题 数组 观察 改变 Knockout      更新时间:2023-09-26

我有一个绑定到属性对象的ko.observableArray()的选择:

<select title="Select Property"
  data-bind="options: $root.properties,
         optionsCaption: '- Select Property -',
         optionsText: 'name',
         optionsValue: 'typeId',
         value: $root.columns()[index]
  "></select>

当有选择时,select元素显示被选择的名称。这工作了一段时间,但现在我需要修改properties observableArray后的选择。一旦我这样做,选择就会返回到optionsCaption。

本页底部是

部分

注2:对生成的选项进行后处理

我认为这可以帮助我将选择设置回显示name,但我还没有弄清楚如何。

除非我可以使用JQuery抓取选择和设置名称?

我想这样写:

$("select[title='Select Property']").setAttribute();

但是选择是在ko foreach中生成的,所以我必须指定元素的索引才能获得它(如何?),即使这样,我也不确定如何使JQuery与knockout一起发挥良好。

我有没有说过我还在学习这些东西?

谢谢。

------------------ EDIT ------------------

显示我如何修改数组:

我从subscribeChanged得到newValueoldValue,然后

if (typeof(newValue) != "undefined") {
  var newProperty = model.allProperties[newValue];
  if (model.properties.indexOf(newProperty) != -1) {
    model.properties.splice(model.properties.indexOf(newProperty), 1);
  }
  model.propertiesInUse[newValue] = index;
}
if (typeof(oldValue) != "undefined") {
  var oldProperty = model.allProperties[oldValue];
  if (model.properties.indexOf(oldProperty) == -1) {
    model.properties.unshift(oldProperty);
  }
  if (model.propertiesInUse[oldValue]) {
    delete model.propertiesInUse[oldValue];
  }
}

就我对你情况的理解

-你需要创建一个动态下拉列表,任何添加的下拉列表都会更新为尚未被选择的值。

-如果一个下拉菜单被删除并且有一个选定的值,该值需要重新添加到其他下拉菜单。

下面是我的方法:

示例:https://jsfiddle.net/9aLvd3uw/251/

HTML:

<!-- ko foreach: MainPropertiesList -->
  <select title="Select Property" data-bind="value:SelectedValue">
     <option data-bind="value:'',text:'-Select Property -'"></option>
      <!-- ko foreach: Options -->
        <option data-bind="value:typeId,text:name"></option>
     <!-- /ko -->
  </select>
  <span data-bind="text:'remove',click:$root.deleteColumn"></span>
<!-- /ko -->
<hr>
<span data-bind="text:'add',click:$root.addColumn"></span>

JS:

var data = [{name:"Property1",typeId:1},{name:"Property2",typeId:2},{name:"Property3",typeId:3},{name:"Property4",typeId:4}];
ko.subscribable.fn.subscribeChanged = function (callback, context) {
    var savedValue = this.peek();
    return this.subscribe(function (latestValue) {
        var oldValue = savedValue;
        savedValue = latestValue;
        callback.call(context, latestValue, oldValue);
    });
};
var DropDownItemViewModel = function (index){
  var self = this;
  self.SelectedValue = ko.observable();
  self.Index = ko.observable(index);
  self.Options = ko.observableArray(($.map(data, function (item) {
    return new OptionItemViewModel(item);
  })));
 self.SelectedValue.subscribeChanged(function(newVal, oldValue){
    if(newVal){
     ko.utils.arrayForEach(appVM.MainPropertiesList(), function (item) {
         ko.utils.arrayForEach(item.Options(), function (item2) {
          if(item2 && item2.typeId() == newVal && self.Index() != item.Index() ){
            item.Options.remove(item2);
           if(oldValue){
              item.Options.push(new OptionItemViewModel({name:"Property" + oldValue , typeId : oldValue}));
           }
        }
      });
    });
     ko.utils.arrayForEach(appVM.SelectedPropertiesList(), function (item) {
      if(item && item.typeId() == oldValue){
         appVM.SelectedPropertiesList.remove(item);
      }
    });
    appVM.SelectedPropertiesList.push(new OptionItemViewModel({name:"Property" + newVal , typeId : newVal}));
    }
  });
}
var OptionItemViewModel = function (data){
  var self = this;
  self.name = ko.observable(data.name);
  self.typeId = ko.observable(data.typeId);
}
var AppViewModel = function(){
  var self = this;
  self.numberOfColumns = ko.observable(2);
  self.properties = ko.observableArray();
  self.MainPropertiesList = ko.observableArray();
  self.SelectedPropertiesList = ko.observableArray();
  for (var i = 0; i <= self.numberOfColumns(); i++) {
     self.MainPropertiesList.push(new DropDownItemViewModel(i));
  }
  self.deleteColumn = function(item){
    self.MainPropertiesList.remove(item);
    self.UpdateDropDowns(item);
  }
  self.addColumn = function(){
     self.MainPropertiesList.push(new DropDownItemViewModel(self.MainPropertiesList().length));
     self.UpdateAddedDropDown();
  }
  self.UpdateAddedDropDown = function(){
    var len = self.MainPropertiesList().length ; 
    ko.utils.arrayForEach(appVM.SelectedPropertiesList(), function (item) {
        ko.utils.arrayForEach(self.MainPropertiesList()[len-1].Options(), function (item2) {
        if(item && item2 && item.typeId() == item2.typeId()){
            self.MainPropertiesList()[len-1].Options.remove(item2);
        }
       });
    });
  }
  self.UpdateDropDowns = function(data){
    if(data.SelectedValue()){
     ko.utils.arrayForEach(self.MainPropertiesList(), function (item) {
         item.Options.push(new OptionItemViewModel({name:"Property" + data.SelectedValue() ,typeId:data.SelectedValue()}));
    });
    }
  }
}
var appVM = new AppViewModel();
ko.applyBindings(appVM);