Reputation: 928
Please see the following example I have created. https://jsfiddle.net/divekarvinit/5vh67sod/4/
In this example, the 'Allowances' model contains various attributes. Out of these attributes, for a particular allowance, which attributes are to be shown on screen are contained in 'fields' array.
In the following HTML code,
<div data-bind="foreach : allowanceList">
<div style="display : block; width : 100%">
<span data-bind="text : allowanceTitle"></span>
</div>
<div style="margin-left : 20px" data-bind="foreach : fields">
<div style="display : block; width : 100%">
<label data-bind="text : title"></label>
<!-- ko if : typeOfField() == "input"-->
<input data-bind="value : '$parentContext.' + allowanceVariable() " />
<!-- /ko -->
</div>
</div>
<br/>
</div>
I want to bind <input>
to the attribute of allowanceList's object whose name is contained in the value of 'allowanceVariable'
variable of 'fields'
array.
For example, for the first iteration of allowanceList
and first iteration of fields
, the allowanceVariable()
has value of 'hours'.
Hence, for this iteration, I want to bind the <input>
to 'hours' field of the allowanceList's
current object.
As seen in the fiddle, at present, knockout only copies $parentContext.hours into input.
How can I achieve the desired result?
Upvotes: 1
Views: 171
Reputation: 35261
In your answer, you are hardcoding the allowanceVariable
s and checking them individually using if-else chains. For every property you add, you'd have to update the if-else
block. It works, but they are no longer dynamic fields
.
Instead, you can use the keyword as
and give an alias to your foreach
binding like this:
<div data-bind="foreach: { data: allowanceList, as: '_allowance'}">
<div style="display : block; width : 100%">
<span data-bind="text : allowanceTitle"></span>
</div>
<div style="margin-left : 20px" data-bind="foreach: { data: _allowance.fields, as: '_field'}">
<div style="display : block; width : 100%">
<label data-bind="text : title"></label>
<!-- ko if : typeOfField() == "input"-->
<input data-bind="value : _allowance[_field.allowanceVariable()]" />
<!-- /ko -->
</div>
</div>
</div>
Mind you, we can make it work without alias as well. Use the $parent
and $data
binding contexts like this:
<div data-bind="foreach : allowanceList">
<div style="display : block; width : 100%">
<span data-bind="text : allowanceTitle"></span>
</div>
<div style="margin-left : 20px; display : block; width : 100%" data-bind="foreach : fields">
<div style="display : block; width : 100%">
<label data-bind="text : title"></label>
<!-- ko if : typeOfField() == "input"-->
<input data-bind="value : $parent[$data.allowanceVariable()]" />
<!-- /ko -->
</div>
</div>
<br/>
</div>
But, I think the former approach is cleaner and easily understandable. Great stuff on creating neat fiddles by the way :)
Upvotes: 1
Reputation: 928
By using function inside the model, the desired result can be achieved. Following is the fiddle which demonstrates the answer.
https://jsfiddle.net/divekarvinit/9fq59gfc/1/
Here, I have called dynamicValue
function of the Field
model of inner for loop and
I have passed $parent
object to it.
In the function, I have checked the value of allowanceVariable
and accordingly returned value of corresponding variable of Allowance
model.
Please suggest any other better solution if applicable as in this solution, I have to hard code names of attributes of Allowance
model in the dynamicValue
function, but, this definitely solves my problem.
Upvotes: 0