Pregunta

I'm having trouble creating a method for naming rows. Row numbers are stored in the database, and I basically want it to be like if the Row # is 1, then the title is 'Contact Info'. At the moment I have this, which works but leads to messy markup as there will be 12 rows with titles.

<!-- ko if: {{ row }} === 1 -->
    <h4>Contact Information</h4>
<!-- /ko -->
<!-- ko if: {{ row }} === 3 -->
    <h4>Opening Times</h4>
<!-- /ko -->
<!-- ko if: {{ row }} === 5 -->
    <h4>Company Details</h4>
<!-- /ko -->

I'm trying to do it within a data-bind, I've started off with this

<h4 data-bind: visible: hasHeaderForRow($data, {{ row }}, text: headerTextForRow($data, {{ row }}))></h4>

But can't work out how to create a model to make this work.

¿Fue útil?

Solución

I would recommend you using good old $index() for fixing your issue. You should add an array rowTitles to your viewmodel as well as getTitleForRow method.

e.g.

rowTitles: ['Contact Information', 'Opening Times', 'Company Details' ],

getTitleForRow: function (index) {
  return this.rowTitles[index];
}

Your markup in this case should look like this:

<div data-bind="foreach: rows">
  <h4 data-bind="text: $parent.getTitleForRow($index())"></h4>
</div>

If rowTitles array is being got from backend, you should make it an observable array and populate it with the data from server.

Otros consejos

Your straight up question is a bit hard to answer, I think you may have an XY-problem here. This answer provides an alternative solution (which may or may not be what you need, but I guess it may help others landing here in any case).

You seem to be missing something in your domain model, something like a "Group" (where both "Contact Information" and "Opening Times" are such Groups). This would allow you to write this kind of KO view:

<!-- ko foreach: groups -->
<h4 data-bind="text: group-title"></h4>
Etc.
<!-- /ko -->

Preferably this grouping is already visible in your database. A normalized design should probably include something like a "Group".

If that's not possibly for some reason, you should preferably have this "Group" concept server side, and send data to Knockout where the bits are already grouped.

If that's also not possible, I'd recommend handling it in your view model, and not in your view. Supposing the following data:

var data = [
    "MARY MARY",
    "Contact information",
    "Mary's Bakery, Main street",
    "Opening Times",
    "10 till 18 hrs",
    "Company details",
    "Bakes the best cookies in town."];

Then you could use the following view models:

var Group = function(txt) {
    var self = this;
    self.txt = ko.observable(txt);
}

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

    self.title = ko.observable(data[0]);

    self.groups = ko.observableArray([]);

    for (var i=0; i < data.length; i++) {
        if (i == 1 || i == 3 || i == 5) { // or whatever "if" logic seems best
            i++;
            self.groups.push(new Group(data[i]));
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top