基本淘汰赛在儿童变化时保存父母

时间:2016-08-31 05:07:02

标签: c# knockout.js viewmodel

我有一个基本的淘汰赛问题: 我有这种格式的对象列表:

 [{ Name: "Colors1", Values: ["red", "yellow", "blue"] },
 { Name: "Colors2", Values: ["red", "pink", "blue"] },
 { Name: "Colors3", Values: ["black", "white", "green"] }]);

我想要一个带有颜色名称的下拉列表。在选择更改时,值中的颜色应显示在文本框中。 在文本框中更改颜色时,应立即更新整个记录。

这就是我所拥有的:

            <div> 
                    <select data-bind="options:myitems, optionsText:'Name', optionsValue:'Name', optionsCaption:'Please select a color', value:selectedColor"></select>

                    <table>
                        <thead>
                            <tr>
                                <th>Color</th>
                            </tr>
                        </thead>
                        <tbody data-bind="foreach:listofColors()?  ">
                            <tr>
                                <td><input data-bind="value:Value, event: { change : $parent.SaveUpdatedColors($root)?}" /></td>
                            </tr>
                        </tbody>
                    </table>
                </div>
        //-----------------------------------   // 
               <script>    
                var  viewModel= function() {
                        var self = this;
                        self.selectedColorChoice = ko.observable();
                        self.listofColors = ko.observableArray();

                        self.myitems = ko.observableArray(
                            [{ Name: "Colors1", Values: ["red", "yellow", "blue"] },
                            { Name: "Colors2", Values: ["red", "pink", "blue"] },
                            { Name: "Colors3", Values: ["black", "white", "green"] }]);
                var getByName = function (items, name) {
                return ko.utils.arrayFirst(items, function (item) {
                    return item.Name === name;
                              });
                           };


   self.selectedColor.subscribe(function(item) //NOT WORKING
    {
        self.listofColors = ko.computed(function () {
            var selColor = getByName(self.myitems(), self.selectedColor);
            return selColor ? ko.utils.arrayMap(selColor.Values, function (item) {
                return {
                    Name: item.Name,
                    Value: item.Value
                };
            }) : [];
        }, this);
    })
                        })

    self.SaveUpdatedColors=function(fullRecord)
    { //logic to update}
                    }
                    ko.applyBindings(new viewModel());
            </script>

我该怎么办?提前谢谢。

1 个答案:

答案 0 :(得分:1)

在我们开始之前:您的代码段中存在相当多的语法错误,以及一些根本没有使用过的东西......我冒昧地移动了一些东西并删除了一些代码。

您希望为颜色字符串创建双向数据绑定,但是您要使用字符串和数组渲染普通对象;那些不会通过value data-bind。

支持更新

创建第二层视图模型

做事的“淘汰方式”是为要渲染和交互的每个项目创建一个视图模型。因此,对于您的情况,我创建了一个ColorItem视图模型。此项目目前仅包含namevalues列表(颜色的字符串名称)。为了便于阅读,我将字符串包装在普通对象中,这样我们就可以通过键入value: value进行数据绑定,而不必使用$data

存储选择并绑定到它

现在有一个ColorItem的列表,我们可以在ColorItem可观察的selectedColor个实例中添加<table>个实例。请注意,您无需选择要存储的属性。您可以存储整个项目!

selectedColor现在使用with: selectedColor绑定绑定到name。这意味着表的上下文是具有valuesko.computed属性的对象。

订阅变更;存储状态

最后,为了能够对任何颜色项中的任何更改做出反应,我们计算出一个“状态”:一个普通的javascript对象,它反映了所有的变化。制作。 (请注意,如果您计划创建一个非常大的应用程序,这可能太昂贵了。)

对于此示例,状态不仅仅是所有可观察属性的展开版本。通过获取<{1}}或ko.pureComputed中的观察值,淘汰赛会自动为您预订任何未来的更改。

我评论了下面示例中的一些代码。如果您了解所有内容并且是否回答了所有问题,请告诉我。

注意:部分代码假设您要添加其他功能,例如更改名称和添加更多颜色。如果您不需要,可以使用常规值替换某些observableobservableArray属性。您还可以删除“临时状态”,仅输出所需的对象格式。

// Our starting data
var colors = [{
  Name: "Colors1",
  Values: ["red", "yellow", "blue"]
}, {
  Name: "Colors2",
  Values: ["red", "pink", "blue"]
}, {
  Name: "Colors3",
  Values: ["black", "white", "green"]
}];

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

  // Create ColorItem viewmodels
  self.listOfColors = ko.observableArray(
    colors.map(ColorItem.createFromData));
  self.selectedColor = ko.observable();

  // Computed state, holds name of current selection and list of items
  self.colorState = ko.pureComputed(function() {
    return {
      selectedColorName: self.selectedColor() ? self.selectedColor().name() : null,
      colorStates: self.listOfColors().map(function(colorItem) {
        return colorItem.state();
      })
    };
  });
  
  // By subscribing to the computed state, we can trigger any other methods
  self.colorState.subscribe(function(newState) {
    // If you want to save to server, you'll need to rate limit updates
    // and abort previous posts
    
    // To convert back to your original format:
    console.log(JSON.stringify(
      newState.colorStates.map(function(itemState) {
        return { Name: itemState.name, Values: itemState.values };
      }))
    );
  });
};


var ColorItem = function(name, values) {
  this.name = ko.observable(name);
  this.values = ko.observableArray(values.map(function(str) {
      return {
        // By wrapping the string in an observable, we can bind 
        // the input's value to it
        value: ko.observable(str)
      };
  }));

  // Color items hold their own state: name and a list of strings
  this.state = ko.pureComputed(function() {
    return {
      name: this.name(),
      values: this.values().map(function(valueObj) {
        return valueObj.value();
      })
    };
  }, this);
};

// A helper function to transform a {Name, Values} object in to a viewmodel
ColorItem.createFromData = function(data) {
  return new ColorItem(data.Name, data.Values);
};

ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div>
  <select data-bind="options:listOfColors, 
                     optionsText:'name', 
                     optionsCaption:'Please select a color',    
                     value:selectedColor"></select>

  <table data-bind="with: selectedColor">
    <thead>
      <tr>
        <th>Color</th>
      </tr>
    </thead>
    <tbody data-bind="foreach:values">
      <tr>
        <td>
          <input data-bind="textInput: value" />
        </td>
      </tr>
    </tbody>
  </table>
</div>