在击倒JS时遇到更多问题,并希望有人能够帮助我。 (我不得不问关于Knockout的问题,我想知道是否应该坚持使用jQuery)
我正在尝试使用两个或三个选项动态创建单选按钮列表。每一行都是一组独立的按钮。
我可以把这个清单写好,但我正在努力找到合适的人来检查。
我的HTML是:
<div data-bind="with: functions" id="ActionWindow">
<h2>bob<span data-bind="text: pgroupname"></span></h2>
<h2>Read & Update Functions</h2>
<div>
<table>
<thead class="FunctionsTableHead">
<tr>
<th class="FunctionName">Function</th>
<th>None</th>
<th>Read</th>
<th>Write</th>
</tr>
</thead>
<tbody class="FunctionsTable" data-bind="foreach: pReadFunctions">
<tr>
<td class="FunctionName" data-bind="text: FunctionName"></td>
<td><label><input type="radio" data-bind="attr: { name: FunctionNum + '-ReadAccessLevel'}, checkedValue: 0, checked: AccessLevel" /></label></td>
<td><label><input type="radio" data-bind="attr: { name: FunctionNum + '-ReadAccessLevel'}, checkedValue: 1, checked: AccessLevel" /></label></td>
<td><label><input type="radio" data-bind="attr: { name: FunctionNum + '-ReadAccessLevel'}, checkedValue: 2, checked: AccessLevel" /></label></td>
</tr>
</tbody>
</table>
</div>
<h2>Action Functions</h2>
<table>
<thead class="FunctionsTableHead">
<tr>
<th class="FunctionName">Function</th>
<th>None</th>
<th>Action</th>
</tr>
</thead>
<tbody class="FunctionsTable" data-bind="foreach: pActionFunctions">
<tr>
<td class="FunctionName" data-bind="text: FunctionName"></td>
<td><label><input type="radio" data-bind="attr: { name: FunctionNum + '-ActionAccessLevel'}, checkedValue: 0, checked: AccessLevel" /></label></td>
<td><label><input type="radio" data-bind="attr: { name: FunctionNum + '-ActionAccessLevel'}, checkedValue: 1, checked: AccessLevel" /></label></td>
</tr>
</tbody>
</table>
我已经为两个单选按钮列表尝试了两种不同的方法,但两种方法都没有效果:
<script type="text/javascript">
//slide animation for lefthand menu
$('.ListDeptLink').click(function () {
$(this).nextAll('.SectListDiv').first().slideToggle(500);
});
$('.ListSectLink').click(function () {
var url = '@Url.Action("DisplayGroup", "AjaxGroup")' + '?GroupId=' + $(this).attr("GroupId") + "&GroupName=" + encodeURIComponent($(this).attr("GroupName"));
$.ajax({
url: url,
contentType: "application/json; charset=utf-8",
type: 'POST',
context: this,
timeout: 60000,
dataType: 'json',
tryCount: 0,
retryLimit: 3,
success: function (data) {
viewModel.functions(new functionsModel(data))
},
error: function (httpRequest, textStatus, errorThrown) {
alert("Error");
}
});
});
function functionsModel(data) {
this.pgroupname = ko.observable(data ? data.GroupName : "");
this.FunctionNum = data ? data.FunctionNum : "";
this.AccessLevel = data ? data.AccessLevel : "";
this.pReadFunctions = ko.observableArray((data ? data.ReadFunctionList : [])
.map(function (item) {
return {
FunctionNum: item.FunctionNum,
FunctionName: item.FunctionName,
AccessLevel: ko.observable(item.AccessLevel)
};
})
);
this.pActionFunctions = ko.observableArray((data ? data.ActionFunctionList : [])
.map(function (item) {
return {
FunctionNum: item.FunctionNum,
FunctionName: item.FunctionName,
AccessLevel: ko.observable(item.AccessLevel)
};
})
);
};
var wrapper = function () {
this.functions = ko.observable(new functionsModel(null));
};
var viewModel = new wrapper();
ko.applyBindings(viewModel);
最后回来的数据示例:
ReadFunctionList":[],"ActionFunctionList": [{"FunctionNum":582,"FunctionName":"Name1","FunctionType":Ignorethis,"GroupNum":1,"AccessLevel":0},{"FunctionNum":502,"FunctionName":"Name2","FunctionType":IgnoreThis,"GroupNum":2,"AccessLevel":0},"GroupName":"Name1"}
AccessLevel决定了应该勾选的内容,因此在本例中,两个项目都应该勾选第一个单选按钮。
提前感谢您的帮助:)
编辑:我已将代码更新到目前为止
答案 0 :(得分:1)
Javascript问题
我认为包装器中的函数应该是一个可观察的,而不是observableArray。
var wrapper = function () {
this.functions= ko.observable(new functionsModel(null));
};
您的pReadFunction和pActionFunction项应具有AccessLevel属性作为observable。您无法通过将单选按钮更改为视图模型获得更新。
// Inside $('.ListSectLink').click
this.pReadFunctions = ko.observableArray( (data ? data.ReadFunctionList : [] )
.map( function(item) {
return {
FunctionNum: item.FunctionNum,
FunctionName: item.FunctionName,
FunctionType: item.FunctionType,
GroupNum: item.GroupNum,
AccessLevel: ko.observable(item.AccessLevel)
};
})
);
// Repeat for pActionFunctions
在你的jsFiddle中,不要在你的点击处理程序中使用AJAX调用,只需直接分配你的样本数据。如果您真的想模拟异步回调,请使用$ .Deferred / resolveWith。
$('.ListSectLink').click(function () {
var testData = ...
viewModel.functions( new functionsModel(testData) );
});
$('.ListSectLink').click(function () {
var testData = ...
var deferred = $.Deferred();
deferred.done( function(data) {
this.functions( new functionsModel(data) );
});
setTimeout( function() {
deferred.resolveWith(viewModel, [testData]);
}, 100);
});
HTML /绑定问题
在你的jsFiddle中它缺少包装器 - &gt;函数绑定。这可能是样本不起作用的原因。假设有类似的东西。
<div data-bind="with: functions" />
输入无线电检查绑定不应该针对$ root。这将是您示例中的 wrapper 实例。给定样本JSON,AccessLevel位于每个ReadFunctionList和ActionFunctionList数组项上,因此使用“$ data.AccessLevel”(或只是“AccessLevel”)来检查数据绑定
检查的绑定与元素的值和后备可观察值进行比较。但元素的绑定是字符串,但在您的示例JSON中,它是数字。这不符合。添加checkedValue数据绑定表达式以覆盖每个单选按钮的“值”为数字。
您还需要为pReadFunction单选按钮使用名称attr绑定,就像使用pActionFunction单选按钮将每行分组到一个集合中一样。您还可以考虑在Read和Action中添加另一个前缀,以防FunctionNum在两个集合之间不唯一。
<input type="radio" data-bind="
attr: { name: 'Action-' + FunctionNum + '-AccessLevel'},
checkedValue: 0,
checked: AccessLevel" />
<input type="radio" data-bind="
attr: { name: 'Action-' + FunctionNum + '-AccessLevel'},
checkedValue: 1,
checked: AccessLevel" />
奖励积分
您也可以使用点击绑定而不是使用jQuery。 click函数将是包装类的函数。您需要传递Url,因为它看起来像是在服务器端生成的。我正在使用一个按钮连接示例的数据绑定。你可能需要帮助razor引擎在data-bind属性中解决客户端和服务器端的问题。我将把它作为练习留给读者;)
这里的好处是所有模型操作都包含在viewModel中。另请注意click数据绑定表达式上的 bind 语句。这是你在函数中获取参数的方法。如果“wrapper”不是根对象,则可能需要将其更改为$ data或$ parent,具体取决于您的realBindings / viewModel结构。在jsFiddle它会工作。
<button data-bind="click: getListSectLink.bind($root, @Url.Action(...)">Get</button>
function wrapper() {
this.functions = ko.observable( new FunctionsModel(null ) );
this.getListSectLink = function(url) {
// ajax stuff
success: function(data) {
this.functions( new functionsModel(data) );
}
};
}
答案 1 :(得分:1)
问题在于Knockout使用精确比较来确定要选择哪个单选按钮,并且绑定到整数checked
值,同时为单选按钮提供字符串attr
值。解决方案是使用checkedValue
绑定(而不是attr
)为单选按钮提供整数值:
<input type="radio" data-bind="checkedValue: FunctionNum, checked: $root.AccessLevel" />
参考:http://knockoutjs.com/documentation/checked-binding.html#parameters