it-swarm.com.de

Wie Verwenden von Aussparung zum Durchlaufen eines Objekts (nicht eines Arrays)

Ich möchte etwas ähnliches wie das Knockout-foreach-Konstrukt verwenden, um die Eigenschaften eines Objekts zu durchlaufen. Hier ist, was ich zu schaffen versuche ...

ERWÜNSCHTES ERGEBNIS

<table>
    <tr>
        <td>Name 1</td>
        <td>8/5/2012</td>
    </tr>
    <tr>
        <td>Name 2</td>
        <td>2/8/2013</td>
    </tr>
</table>

Mein Modell sieht jedoch so aus ...

JS

function DataModel(){
    this.data = ko.observableArray([{
                        entityId: 1,
                        props: {
                            name: 'Name 1',
                            lastLogin: '8/5/2012'
                        }
                    },
                    {
                        entityId: 2,
                        props: {
                            name: 'Name 2',
                            lastLogin: '2/8/2013'
                        }
                    }]);
}

var dataModel = new DataModel();
ko.applyBindings(dataModel);

Jede Zeile hat eine entityId und Requisiten, die selbst ein Objekt sind. Diese Vorlage funktioniert nicht, aber wie würde ich sie ändern, um die gewünschte Tabelle oben zu generieren?

BEARBEITEN: Die props in diesem Beispiel sind name und lastLogin, aber ich brauche eine Lösung, die das, was in props enthalten ist, nicht anspricht.

Ich habe diese GEIGE auch.

HTML

<div data-bind="template: { name: 'template', data: $data }"></div>

<script type="text/html" id="template">
    <table>
        <tr data-bind="foreach: data()">
            <td data-bind="text: entityId"></td>  
        </tr>
    </table> 
</script>
41
John Livermore

Sie können immer einen Bindungshandler erstellen, um die Umwandlung abzuwickeln.

ko.bindingHandlers.foreachprop = {
  transformObject: function (obj) {
    var properties = [];
    ko.utils.objectForEach(obj, function (key, value) {
      properties.Push({ key: key, value: value });
    });
    return properties;
  },
  init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
    var properties = ko.pureComputed(function () {
      var obj = ko.utils.unwrapObservable(valueAccessor());
      return ko.bindingHandlers.foreachprop.transformObject(obj);
    });
    ko.applyBindingsToNode(element, { foreach: properties }, bindingContext);
    return { controlsDescendantBindings: true };
  }
};

Dann bewerben Sie sich:

<div data-bind="template: { name: 'template', data: $data }"></div>

<script type="text/html" id="template">
    <table>
        <tbody data-bind="foreach: data">
            <tr data-bind="foreachprop: props">
                <td data-bind="text: value"></td>
            </tr>
        </tbody>
    </table> 
</script>
46
Jeff Mercado

In einem modernen Browser (oder mit einem geeigneten Polyfill) können Sie über Object.keys(obj) iterieren (die Methode gibt nur eigene aufzählbare Eigenschaften zurück, sodass keine zusätzliche hasOwnProperty-Prüfung erforderlich ist.

<table>
  <tbody data-bind="foreach: {data: data, as: '_data'}">
    <tr data-bind="foreach: {data: Object.keys(props), as: '_propkey'}">
      <th data-bind="text: _propkey"></th>
      <td data-bind="text: _data.props[_propkey]"></td>
    </tr>
  </tbody>
</table>

gefiedert .

NB: Ich war einfach neugierig, ob das funktionieren würde, der Schablonenkörper oben ist stärker verschmutzt als das, was ich in der Produktion verwenden möchte (oder auf ein paar Monate später zurückkommen und wie "wtf" sein). .

Eine benutzerdefinierte Bindung wäre eine bessere Option, meine persönliche Präferenz wäre jedoch die Verwendung eines berechneten beobachtbaren oder eines - beschreibbaren berechneten Beobachtbaren (Letzteres wäre praktisch, wenn Sie mit json Antworten a-la restful api arbeiten).

61
o.v.

Dies ist eine Modifikation von Jeffs Antwort, wobei der Bindungskontext erhalten bleibt

ko.bindingHandlers.eachProp = {
    transformObject: function (obj) {
        var properties = [];
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                properties.Push({ key: key, value: obj[key] });
            }
        }
        return ko.observableArray(properties);
    },
    init: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var value = ko.utils.unwrapObservable(valueAccessor()),
            properties = ko.bindingHandlers.eachProp.transformObject(value);

        ko.bindingHandlers['foreach'].init(element, properties, allBindingsAccessor, viewModel, bindingContext)
        return { controlsDescendantBindings: true };
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
        var value = ko.utils.unwrapObservable(valueAccessor()),
            properties = ko.bindingHandlers.eachProp.transformObject(value);

        ko.bindingHandlers['foreach'].update(element, properties, allBindingsAccessor, viewModel, bindingContext)
        return { controlsDescendantBindings: true };
    }
};

Bewerben Sie sich jetzt mit Eltern und Wurzel:

<table>
    <tbody data-bind="foreach: data">
        <tr data-bind="eachProp: props">
            <td data-bind="text: value, click: $root.doSomething"></td>
        </tr>
    </tbody>
</table> 
21
Jitters
<table>
    <tr data-bind="foreach: {data: data, as: 'item'}">
        <td data-bind="foreach: { data: Object.keys(item), as: 'key' }">
            <b data-bind="text: item[key]"></b>
        </td>  
    </tr>
</table>

function DataModel(){
this.data = ko.observableArray([{
                    entityId: 1,
                    props: {
                        name: 'Name 1',
                        lastLogin: '8/5/2012'
                    }
                },
                {
                    entityId: 2,
                    props: {
                        name: 'Name 2',
                        lastLogin: '2/8/2013'
                    }
                }]);
}

var dataModel = new DataModel();
ko.applyBindings(dataModel);

Hoffe das ist hilfreich (verzeihen Sie die Kürze)

Blinddarm:

Hier ist ein funktionierendes Beispiel, das getestet wurde ...

<table class="table table-hover">
    <thead>
        <tr>
            <!-- ko foreach: gridOptions.columnDefs -->
            <th data-bind="text: displayName"></th>
            <!-- /ko -->
        </tr>
    </thead>
    <tbody>
        <!-- ko foreach: {data: gridOptions.data, as: 'item'} -->
        <tr>
            <!-- ko foreach: {data: Object.keys(item), as: 'key'} -->
            <td>
                <span data-bind="text: item[key]"></span>
            </td>
            <!-- /ko -->
        </tr>
        <!-- /ko -->
    </tbody>
</table>
2
Cody

Angeblich gibt es ein tieferes Problem ( siehe diesen Thread bei Google-Gruppen ), das heißt, Foreach behandelt das Objekt als ein Wörterbuch mit Parametern und nicht als zu iterierende Auflistung. 

Meine bisher beste Lösung ist die Kombination von foreach in Object.keys(myobject) und 'with' bindendem Kontext.

2
Jakub Macek

Vereinfachte Antwort, um mit jedem Basisobjekt zu arbeiten, arbeitete für mich:

<!-- ko foreach: {data: Object.keys(myObj)} -->
    <span data-bind="text: $data"></span> 
    <span data-bind="text: $parent.myObj[$data]"></span>
<!-- /ko -->
2
Andrew

Ich bin ein bisschen spät dran, aber ich denke, das sollte funktionieren, eine einfache Lösung ohne Vorlage.

var json = [
	{
		"PortfolioCompanyId":240,
		"dt":"2018-12-31 00:00:00.0",
		"ValuationDate":"2017-09-30 00:00:00.0",
		"capitalexpenditure":-5555660.0,
		"workingcapitalchange":-812350.0
	},
	{
		"PortfolioCompanyId":240,
		"dt":"2019-12-31 00:00:00.0",
		"ValuationDate":"2017-09-30 00:00:00.0",
		"capitalexpenditure":-5613520.0,
		"workingcapitalchange":-893530.0
	},
	{
		"PortfolioCompanyId":240,
		"dt":"2020-12-31 00:00:00.0",
		"ValuationDate":"2017-09-30 00:00:00.0",
		"capitalexpenditure":-5674130.0,
		"workingcapitalchange":-982850.0
	},
	{
		"PortfolioCompanyId":240,
		"dt":"2021-12-31 00:00:00.0",
		"ValuationDate":"2017-09-30 00:00:00.0",
		"capitalexpenditure":-6241543.0,
		"workingcapitalchange":-1081135.0
	},
	{
		"PortfolioCompanyId":240,
		"dt":"2022-12-31 00:00:00.0",
		"ValuationDate":"2017-09-30 00:00:00.0",
		"capitalexpenditure":-6865697.3,
		"workingcapitalchange":-1189248.5
	}
];

var DataModel = function () {
            this.jsonArray = ko.observable(json);
        };
ko.applyBindings(new DataModel());
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<table class="table" data-bind="foreach:jsonArray">
       <tr data-bind="foreach:Object.keys($data)"> <!-- JSON Object -->
         <td data-bind="text : $parent[$data]"></td>
       </tr>
    </table>
    
    

0
Sufiyan Ansari

(Nicht streng über die Eigenschaften iteriert, aber erstellt die Tabelle oben)

<div data-bind="template: { name: 'template', data: $data }"></div>

<script type="text/html" id="template">
    <table data-bind="foreach: data()">
        <tr>
            <td data-bind="text: props.name"></td>  
            <td data-bind="text: props.lastLogin"></td>  
        </tr>
    </table>
</script>

aktualisiert: http://jsfiddle.net/cwnEE/7/

0
paul