用于添加/删除对象属性的Knockout或其他JavaScript

时间:2016-04-28 14:47:28

标签: javascript html knockout.js

我想构建一个HTML页面,允许用户构建一个对象,然后可以将其作为JSON发布到内部托管服务(类似于Chrome Advanced Rest Client)。用户必须能够添加和删除属性。

我的模型不正确,因为每个属性都被视为具有属性“name”和“value”的对象。我最终得到了一个对象数组,而不是具有属性的对象。

以下是HTML的摘录:

   <table>
        <thead>
            <tr>
                <th>Property Name</th>
                <th>Property Value</th>
                <th></th>
            </tr>            
        </thead>
        <tbody data-bind="foreach: myFieldList">
            <tr>
                <td><input data-bind="value: name" /></td>
                <td><input data-bind="value: value" /></td>
                <td><span class="removeVar" data-bind="click: removeProperty">Remove property</span></td>
            </tr>
        </tbody>
    </table>
    <p>
        <span id="addVar" data-bind="click: addProperty">Add Property</span>
    </p>
<textarea name="tasks" data-bind="value: ko.toJSON(myFieldList)"></textarea>

这是JS:

<script type="text/javascript">

    function dynamicProperty(name, value) {
        var self = this;
        this.name = name;
        this.value = value;
    }

    function fieldModel() {
        var self = this;           
//start with 2 empty properties
        self.myFieldList = ko.observableArray([
            new dynamicProperty("", ""),
            new dynamicProperty("","")
        ]);

        var noTracker = self.myFieldList.length;

        self.removeProperty = function (dynamicProperty) {
            self.myFieldList.remove(dynamicProperty);
        }

        self.addProperty = function () {
            noTracker++;
            self.myFieldList.push(new dynamicProperty(this.name,this.value));
        }
    }

    ko.applyBindings(fieldModel);

</script>

我在textarea中得到的是这样输出:

[{"name":"test name 1","value":"test value 1"},{"name":"test name 2","value":"test value 2"}]

我想要的是这样输出:

{"test name 1":"test value 1","test name 2":"test value 2"}

我担心这是微不足道的,但在我的辩护中,我对JS和Knockout来说是一个新手,所以你能提供的任何帮助都会非常感激。感谢。

2 个答案:

答案 0 :(得分:1)

您需要的是&#34; reducer&#34;。

一个简单的(天真的)实现就是:

function reduce(input, step, init) {
  for(var i = 0; i < input.length; i++) {
    init = step(init, input[i]);
  }

  return init;
}

然后你这样称呼它:

var in = [{"name":"test name 1","value":"test value 1"},{"name":"test name 2","value":"test value 2"}];

var out = reduce(in, function(result, item) {
  result[item.name] = item.value;
  return result;
}, {});

console.log(out);

它做的是它遍历你的数组并且&#34;累积&#34;单个项目中每个步骤的结果。可以是数组中数字的总和,其中&#34;累加器&#34;将是一个数字而不是一个对象。

我建议你不要自己编写,而是使用lodash,它会附带一个_.reduce功能进行优化。

答案 1 :(得分:1)

你可能想要做这样的事情来完成它。
示例:https://jsfiddle.net/9aLvd3uw/79/
HTML

<table>
        <thead>
            <tr>
                <th>Property Name</th>
                <th>Property Value</th>
                <th></th>
            </tr>            
        </thead>
        <tbody data-bind="foreach: myFieldList">
            <tr>
                <td><input data-bind="textInput: name" /></td>
                <td><input data-bind="textInput: value" /></td>
                <td><span class="removeVar" data-bind="click: removeProperty">Remove property</span></td>
            </tr>
        </tbody>
    </table>
    <p>
        <span id="addVar" data-bind="click: addProperty">Add Property</span>
    </p>
<textarea name="tasks" data-bind="value: myFieldList2"></textarea>

JS

function dynamicProperty(name, value) {
    var self = this;
    self.name = ko.observable(name || '');
    self.value = ko.observable(value || '');
}

function fieldModel() {
    var self = this; 
    self.name = ko.observable();
    self.value = ko.observable();
    self.myFieldList = ko.observableArray([
        new dynamicProperty("test_name_1", "test value 1"),
        new dynamicProperty("test_name_2","test value 2")
    ]);

    var noTracker = self.myFieldList.length;

    self.myFieldList2 = ko.computed(function () {
       var string = '{';
       ko.utils.arrayForEach(self.myFieldList(), function (item) {
          string += item.name() + ': ' + item.value() + ',';
       });
       string = string.replace(/,\s*$/, "");
       string+='}';
       return  string;
    });

    self.removeProperty = function (dynamicProperty) {
        self.myFieldList.remove(dynamicProperty);
    }

    self.addProperty = function () {
        noTracker++;
        self.myFieldList.push(new dynamicProperty('',''));
    }
}

ko.applyBindings(fieldModel);