Reputation: 1041
I want looping my form-group
inside form-horizontal
using foreach
from knockout. I have condition when Id
is 1 and 2, this should be grouped inside <fieldset>
. I already tried when just 1 condition is working normally, but when multiple 1 and 2 it's not working.
Code Sample:
<div class="form-horizontal" data-bind="foreach: forArray()">
<!-- ko if: Id() === 1 -->
<fieldset>
<legend>
Foo
</legend>
<!-- /ko -->
<!-- ko if: Id() === 1 || Id() === 2 -->
<div class="form-group">
<label class="control-label col-sm-5"><span data-bind="html: NameColumn"></span></label>
<div class="col-sm-7">
<input type="text" data-bind="value: Id" />
</div>
</div>
<!-- /ko -->
<!-- ko if: Id() === 2 -->
</fieldset>
<br />
<!-- /ko -->
<!-- ko if: Id() !== 1 && Id() !== 2 -->
<div class="form-group">
<label class="control-label col-sm-5"><span data-bind="html: NameColumn"></span></label>
<div class="col-sm-7">
<input type="text" data-bind="value: Id" />
</div>
</div>
<!-- /ko -->
Upvotes: 1
Views: 233
Reputation: 35202
First of all, your containerless control flow syntax won't work. You should treat them as if they are real html container element like you would with a <div>
tag.
From the documentation:
The
<!-- ko -->
and<!-- /ko -->
comments act as start/end markers, defining a “virtual element” that contains the markup inside. Knockout understands this virtual element syntax and binds as if you had a real container element.
Even if you fix your syntax, it won't display your desired output. A single looping through forArray
can't create this functionality, because it will create more than one fieldset
element for both Id
1 and 2. So, you need to create a computed
property. This computed property will have 2 array properties:
lessThanTwo
: push the items with Id
s 1 and 2 moreThanTwo
: push the items with Id
greater than 2Every time the original forArray
changes, groupedArray
gets computed again. You can test this by changing the Id
input of Ronaldo
to 5. That item will get moved outside of the fieldset
.
Use the with
binding to create a new binding context in form-horizontal
div
const viewModel = function() {
const self = this;
self.forArray = ko.observableArray([
{ NameColumn: '<u>Messi</u>', Id: ko.observable(1) },
{ NameColumn: '<b>Ronaldo</b>', Id: ko.observable(2) },
{ NameColumn: '<i>Griezmann</i>', Id: ko.observable(3) },
{ NameColumn: '<u>Mbappé</u>', Id: ko.observable(4) }
]);
self.groupedArray = ko.computed(() => {
const groupedObject = {
lessThanTwo: [],
moreThanTwo: []
};
self.forArray().forEach(item => {
// if Id() > 2 push it a moreThanTwo property
// otherwise push it to lessThanTwo property
if (item.Id() == 1 || item.Id() == 2)
groupedObject.lessThanTwo.push(item);
else
groupedObject.moreThanTwo.push(item);
})
return groupedObject;
})
}
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="form-horizontal" data-bind="with: groupedArray">
<fieldset>
<legend>
Foo
</legend>
<!-- ko foreach: lessThanTwo -->
<div class="form-group">
<label class="control-label col-sm-5"><span data-bind="html: NameColumn"></span></label>
<div class="col-sm-7">
<input type="text" data-bind="value: Id" />
</div>
</div>
<!-- /ko -->
</fieldset>
<br />
<!-- ko foreach: moreThanTwo -->
<div class="form-group">
<label class="control-label col-sm-5"><span data-bind="html: NameColumn"></span></label>
<div class="col-sm-7">
<input type="text" data-bind="value: Id" />
</div>
</div>
<!-- /ko -->
</div>
Upvotes: 1
Reputation: 19
Looks like you have a little mess with ko-/ko tag pairs
Form what you rote <fieldset>
will be opened if condition Id() === 1
is valid but will be closed if Id() === 2
Upvotes: 1