MVC 5 的 Knockout 绑定 Select 更改
Knockout Binding Select Change with MVC 5
我在我的 MVC 应用程序模型上使用 Knockout 的 "foreach" 函数来加载 table 下拉选项。当所选下拉值发生变化时,我需要在模型中跟踪该变化。
我尝试在模型中的元素上使用订阅选项,但是当它发生变化时,我绑定到它的函数没有触发。我知道有几种方法可以实现此更改,但我更愿意坚持使用这种定义函数的格式,如视图底部所示。
型号:
public class ProfileLookAndFeelViewModel : StandardLayoutViewModel
{
public ProfileLookAndFeelViewModel()
{
Form = new FormGroup();
PriceUOMDropdownOptions = new PriceUOM();
UOMInformation = new UOMInformationGroup();
}
public FormGroup Form { get; set; }
public PriceUOM PriceUOMDropdownOptions { get; set; }
public UOMInformationGroup UOMInformation { get; set; }
public class FormGroup
{
public bool FormValueChanged { get; set; }
}
public class PriceUOM
{
public int Id { get; set; }
public String Name { get; set; }
public string Code { get; set; }
}
public class PriceUOMOverride
{
public string ItemDescription { get; set; }
public string TemplateCode { get; set; }
public string UOMDesc { get; set; }
public List<PriceUOM> PriceUOMDropdownOptions { get; set; }
public int SelectedPriceUOM { get; set; }
public int SelectedPriceUOMOriginal { get; set; }
public bool SelectedPriceUOMChanged { get; set; }
}
public class UOMInformationGroup
{
public UOMInformationGroup()
{
UOMs = new List<PriceUOMOverride>();
}
public List<PriceUOMOverride> UOMs { get; set; }
public bool UOMsChanged { get; set; }
}
}
查看:
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>Description</th>
<th>Template Code</th>
<th>Default UOM</th>
</tr>
</thead>
<tbody>
<!-- ko foreach: $root.UOMInformation.UOMs -->
<tr>
<td data-bind="text: ItemDescription"></td>
<td data-bind="text: TemplateCode"></td>
<td class="center" >
<select data-bind="options: PriceUOMDropdownOptions, optionsText: 'Code', optionsValue: 'Id', value: SelectedPriceUOM, css: { important: SelectedPriceUOMChanged() == true }"></select>
</td>
</tr>
<!-- /ko -->
</tbody>
</table>
<script type="text/javascript">
$(function () {
var vmProfileLookAndFeel = function () { var self = this; };
vmProfileLookAndFeel = ko.mapping.childrenIndependently($.parseJSON('@Html.RawJsonForKoMapping(Model)'), ["UOMInformation", "Form", "PriceUOMDropdownOptions"]);
vmProfileLookAndFeel.UOMInformation.UOMs.subscribe(function (newValue) {
vmProfileLookAndFeel.ValueChanged();
});
vmProfileLookAndFeel.ValueChanged = function () {
//Do something;
};
ko.applyBindings(vmProfileLookAndFeel);
});
</script>
我尝试了这个建议,但这里的答案不是从 MVC 模型加载数据,而是从硬编码数组加载数据
Subscribe to select item from foreach loop
编辑:
我更新了视图以反映将数组添加为可观察数组。
这是我调用来映射对象的函数
ko.mapping.childrenIndependently = function (jsObject, childrenArray) {
var mapping = {
"ignore": childrenArray
}
var vm = ko.mapping.fromJS(jsObject, mapping);
// handle children
for (var childrenArrayIndex = 0; childrenArrayIndex < childrenArray.length; childrenArrayIndex++) {
if (jsObject.hasOwnProperty(childrenArray[childrenArrayIndex])) {
// if the property is an array, create an objservable array
// and map each child
// else map the property
if ($.isArray(jsObject[childrenArray[childrenArrayIndex]])) {
vm[childrenArray[childrenArrayIndex]] = ko.observableArray();
for (var childObjectArrayIndex = 0; childObjectArrayIndex < jsObject[childrenArray[childrenArrayIndex]].length; childObjectArrayIndex++) {
vm[childrenArray[childrenArrayIndex]].push(ko.mapping.childrenIndependently(jsObject[childrenArray[childrenArrayIndex]][childObjectArrayIndex], childrenArray.slice(childrenArrayIndex)));
}
}
else {
vm[childrenArray[childrenArrayIndex]] = ko.mapping.childrenIndependently(jsObject[childrenArray[childrenArrayIndex]], childrenArray.slice(childrenArrayIndex));
}
}
}
return vm;
};
对于这种情况,我最终在 <select>
元素之后添加了一个隐藏的计算函数,每次添加行时都会调用该函数。从那里我可以在生成对象时对其进行操作。
<td class="center" >
<select data-bind="options: PriceUOMDropdownOptions, optionsText: 'Code', optionsValue: 'Id', value: SelectedPriceUOM, css: { important: SelectedPriceUOMChanged() == true }"></select>
<span class="hide" data-bind="text: $root.OnTheFlyCalculations($data)()"></span>
</td>
新功能
vmProfileLookAndFeel.OnTheFlyCalculations = function (item) {
return ko.computed({
read: function () {
return item.SomethingChanged(true);
}
}, vmProfileLookAndFeel)
};
我在我的 MVC 应用程序模型上使用 Knockout 的 "foreach" 函数来加载 table 下拉选项。当所选下拉值发生变化时,我需要在模型中跟踪该变化。
我尝试在模型中的元素上使用订阅选项,但是当它发生变化时,我绑定到它的函数没有触发。我知道有几种方法可以实现此更改,但我更愿意坚持使用这种定义函数的格式,如视图底部所示。
型号:
public class ProfileLookAndFeelViewModel : StandardLayoutViewModel
{
public ProfileLookAndFeelViewModel()
{
Form = new FormGroup();
PriceUOMDropdownOptions = new PriceUOM();
UOMInformation = new UOMInformationGroup();
}
public FormGroup Form { get; set; }
public PriceUOM PriceUOMDropdownOptions { get; set; }
public UOMInformationGroup UOMInformation { get; set; }
public class FormGroup
{
public bool FormValueChanged { get; set; }
}
public class PriceUOM
{
public int Id { get; set; }
public String Name { get; set; }
public string Code { get; set; }
}
public class PriceUOMOverride
{
public string ItemDescription { get; set; }
public string TemplateCode { get; set; }
public string UOMDesc { get; set; }
public List<PriceUOM> PriceUOMDropdownOptions { get; set; }
public int SelectedPriceUOM { get; set; }
public int SelectedPriceUOMOriginal { get; set; }
public bool SelectedPriceUOMChanged { get; set; }
}
public class UOMInformationGroup
{
public UOMInformationGroup()
{
UOMs = new List<PriceUOMOverride>();
}
public List<PriceUOMOverride> UOMs { get; set; }
public bool UOMsChanged { get; set; }
}
}
查看:
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>Description</th>
<th>Template Code</th>
<th>Default UOM</th>
</tr>
</thead>
<tbody>
<!-- ko foreach: $root.UOMInformation.UOMs -->
<tr>
<td data-bind="text: ItemDescription"></td>
<td data-bind="text: TemplateCode"></td>
<td class="center" >
<select data-bind="options: PriceUOMDropdownOptions, optionsText: 'Code', optionsValue: 'Id', value: SelectedPriceUOM, css: { important: SelectedPriceUOMChanged() == true }"></select>
</td>
</tr>
<!-- /ko -->
</tbody>
</table>
<script type="text/javascript">
$(function () {
var vmProfileLookAndFeel = function () { var self = this; };
vmProfileLookAndFeel = ko.mapping.childrenIndependently($.parseJSON('@Html.RawJsonForKoMapping(Model)'), ["UOMInformation", "Form", "PriceUOMDropdownOptions"]);
vmProfileLookAndFeel.UOMInformation.UOMs.subscribe(function (newValue) {
vmProfileLookAndFeel.ValueChanged();
});
vmProfileLookAndFeel.ValueChanged = function () {
//Do something;
};
ko.applyBindings(vmProfileLookAndFeel);
});
</script>
我尝试了这个建议,但这里的答案不是从 MVC 模型加载数据,而是从硬编码数组加载数据
Subscribe to select item from foreach loop
编辑:
我更新了视图以反映将数组添加为可观察数组。
这是我调用来映射对象的函数
ko.mapping.childrenIndependently = function (jsObject, childrenArray) {
var mapping = {
"ignore": childrenArray
}
var vm = ko.mapping.fromJS(jsObject, mapping);
// handle children
for (var childrenArrayIndex = 0; childrenArrayIndex < childrenArray.length; childrenArrayIndex++) {
if (jsObject.hasOwnProperty(childrenArray[childrenArrayIndex])) {
// if the property is an array, create an objservable array
// and map each child
// else map the property
if ($.isArray(jsObject[childrenArray[childrenArrayIndex]])) {
vm[childrenArray[childrenArrayIndex]] = ko.observableArray();
for (var childObjectArrayIndex = 0; childObjectArrayIndex < jsObject[childrenArray[childrenArrayIndex]].length; childObjectArrayIndex++) {
vm[childrenArray[childrenArrayIndex]].push(ko.mapping.childrenIndependently(jsObject[childrenArray[childrenArrayIndex]][childObjectArrayIndex], childrenArray.slice(childrenArrayIndex)));
}
}
else {
vm[childrenArray[childrenArrayIndex]] = ko.mapping.childrenIndependently(jsObject[childrenArray[childrenArrayIndex]], childrenArray.slice(childrenArrayIndex));
}
}
}
return vm;
};
对于这种情况,我最终在 <select>
元素之后添加了一个隐藏的计算函数,每次添加行时都会调用该函数。从那里我可以在生成对象时对其进行操作。
<td class="center" >
<select data-bind="options: PriceUOMDropdownOptions, optionsText: 'Code', optionsValue: 'Id', value: SelectedPriceUOM, css: { important: SelectedPriceUOMChanged() == true }"></select>
<span class="hide" data-bind="text: $root.OnTheFlyCalculations($data)()"></span>
</td>
新功能
vmProfileLookAndFeel.OnTheFlyCalculations = function (item) {
return ko.computed({
read: function () {
return item.SomethingChanged(true);
}
}, vmProfileLookAndFeel)
};