Dynamic data binding to nested properties in knock

2019-04-14 15:48发布

问题:

I have a table, data-bound via Knockout js. On each row is a link that I hope to display a modal dialog that will contain input fields that will also bind with my view model.

This is my server side view model

public class ViewModel
{
    ...//String getters/setters
     public IList<SubViewModel> SubViewModels{get;set;} // contains a couple of String properties
     ...
}

I then succesfully serialize this in the client and bind to a table. Each table row has a link:

<script type="text/html" id="myRowTemplate">
    <tr>
    <td><a href="#" data-bind="click: function(){ myModel.doStuffInADialog($data) }">Do stuff in a popup</a></td>
... other editable text fields, all playing nicely

This function gets called correctly, but I want to pass in the current selected row data to the template:

var viewModel = {
    ...
    doStuffInADialog: function (selectedRowData) {
        //how to pass this selectedRowData to the template?
        d.dialog({ ... jquery dialog stuff });
        ...

this is the template I want to use:

<script type="text/html" id="nestedPropertyTemplate">
    <div class="form-row">
        <div>
            <label>${someFieldOnNestedProperty}</label>
        </div>
        <div class="field">
            <input data-bind="value: Value"/>
        </div>            
    <br />
    </div>
</script>

and here's the div I'll use for the dialog

<div data-bind=" template : { name: 'nestedPropertyTemplate', data : SubViewModels() }" style="display: none" class="dialog">
</div>

So, in summary .. I would like to know if there is a way / the best way to:

  • Bind a template to a nested property of my JSON object
  • Use a jQuery dialog to show the contents of the div that uses the template, and have the fields within the dialog databound to my knockoutjs view model
  • inject the current row data dynamically into the template / dialog

回答1:

If I have understood your question correctly, I would add a property to your view model to store the currently selected row eg:

myRows: ko.observableArray(....),
myCurrentlySelectedRow: ko.observable(null)  

... then in your click handler set the selected row:

doStuffInADialog: function (selectedRowData) {   
     myCurrentlySelectedRow(selectedRowData);
     .....
}

Finally, bind your template to the currently selected row:

<div data-bind=" template : { name: 'nestedPropertyTemplate', data : viewModel.myCurrentlySelectedRow() }"

That way your template will fire and re-render the contents whenever your selected row changes satifying your requirement for "inject the current row data dynamically into the template / dialog"