드롭 다운이 변경 될 때 잘못된 바인딩 처리기가 호출되는 매우 이상한 문제가 있습니다. jQuery 1.9.1과 함께 Knockout 3.1을 사용하고 있습니다. 직원을 쉽게 찾을 수 있도록 일련의 계단식 드롭 다운이 있습니다.
여기에 무슨 일이 벌어집니다. 페이지가로드되면 각 핸들러가 예상대로 호출됩니다. 나는의 값을 변경하면 하지,라고 처리기를 예상대로. 드롭 다운 을 제대로 채우기 위해 호출해야하는 전혀 호출되지 않습니다 . 그러나 변경하면 , 가 호출되고 예상대로 작동합니다.#AssignedDepartment
serviceAreaSelect
departmentSelect
departmentSelect
#AssignedServiceAreaName
#AssignedServiceAreaName
serviceAreaSelect
여기서 무슨 일이 벌어 질까요? 이 코드는 Knockout 2.x에서 잘 작동했습니다.
다음은 세 개의 연속 드롭 다운에 대한 세 가지 핸들러 중 두 가지입니다.
// Department Selected
ko.bindingHandlers.departmentSelect = {
update: function (element, valueAccessor, allBindingsAccessor, vm) {
var el = $(element).find("option:selected");
console.log("Department Selected: ", el.val());
if (el.length > 0) {
vm.deptName(el.text());
$.get('/customerservice/jsonproxy/servicearealist', { deptID: el.val() }, function (response) { vm.ServiceArea(response); }, 'json');
}
}
}
// Service Area Selected
ko.bindingHandlers.serviceAreaSelect = {
update: function (element, valueAccessor, allBindingsAccessor, vm) {
var el = $(element).find("option:selected");
console.log("Service Area Selected: ", el.val());
if (el.length > 0) {
vm.ServiceAreaName(el.text());
$.get('/customerservice/jsonproxy/employeelist', { deptID: vm.deptID, serviceAreaID: el.val() }, function (response) {
vm.EmployeeList(response[0].Employees);
vm.EmployeeList.unshift({ EmployeeName: "None Assigned", EmployeeID: "" });
}, 'json');
}
}
};
다음은 HTML입니다.
<div class="row-fluid">
<div class="span4">
@Html.MyLabelFor(m => m.Department, new { @class = "control-label" })
<select class="span12" id="AssignedDepartment" name="AssignedDepartment"
data-bind="options: dept, optionsCaption: 'Select a department', optionsValue: function (item) { return item.DepartmentID }, optionsText: function (item) { return item.DepartmentName; }, value: deptID, departmentSelect: deptID"></select>
<span data-bind="text: deptID"></span><span data-bind=" text: deptName"></span>
@Html.HiddenFor(m => m.Department, new { data_bind = "value: deptName" })
@Html.HiddenFor(m => m.DepartmentCode, new { data_bind = "value: deptID" })
</div>
<div class="span4">
@Html.MyLabelFor(m => m.ServiceArea, new { @class = "control-label" })
<select class="span12" id="AssignedServiceAreaName" name="AssignedServiceArea" data-bind="options: ServiceArea, optionsCaption: 'Select a Service Area', optionsValue: function (item) { return item.ServiceAreaID; }, optionsText: function (item) { return item.ServiceAreaName; }, value: ServiceAreaID, serviceAreaSelect: ServiceAreaID"></select>
@Html.HiddenFor(m => m.ServiceArea, new { @data_bind = "value: ServiceAreaName" })
@Html.HiddenFor(m => m.ServiceAreaCode, new { @data_bind = "value: ServiceAreaID" })
@*<span data-bind="text: ServiceAreaID"></span><span data-bind=" text: ServiceAreaName"></span>*@
</div>
<div class="span4">
@Html.MyLabelFor(m => m.Employee, new { @class = "control-label" })
<select class="span12" id="AssignedEmployee" name="AssignedEmployee" data-bind="options: EmployeeList, optionsCaption: 'None Assigned', optionsValue: function (item) { return item.EmployeeID; }, optionsText: function (item) { return item.EmployeeName; }, value: EmployeeID, employeeSelect: EmployeeID"></select>
@*<span data-bind="text: EmployeeID"></span><span data-bind=" text: EmployeeName"></span>*@
@Html.HiddenFor(m => m.Employee, new { data_bind = "value: EmployeeName" })
@Html.HiddenFor(m => m.EmployeeID, new { data_bind = "value: EmployeeID" })
</div>
</div>
update
콜백은 모델 변경이 아닌 장소의 응답에 DOM을 다시 그릴 수 있도록 설계되었습니다 to update model when DOM changes
(코드에서 알 수 있듯이).
update
DOM을 업데이트하기 위해 콜백에서 모델의 값만 읽고 콜백 내부에서 모델을 변경하지 마십시오 update
.
value
바인딩 (값 : deptID)은 동기화 모델 (deptID), 다른 bindingHandler 필요하지 않습니다와 DOM을.
당신이 원하는 것은 단지 do something when model changes
.
ko.bindingHandlers.departmentSelect
및 ko.bindingHandlers.serviceAreaSelect
및ko.bindingHandlers.employeeSelect
departmentSelect: deptID
, serviceAreaSelect: ServiceAreaID
및 employeeSelect: EmployeeID
.예, 여전히 ko
스타일이 아닌 코드 가 self.deptName($('#AssignedDepartment option:selected').text())
있습니다.
이상적으로 ko 앱에서 모든 DOM 조작은 bindingHandler init
및 update
콜백 내에 숨겨져 야합니다 .
문제를 해결하는 방법에는 두 가지가 있습니다.
A) deptName을 자동으로 업데이트합니다.
self.deptID.subscribe(function (val) {
if (val !== undefined && val !== null) {
$.get('/customerservice/jsonproxy/servicearealist', { deptID: val }, function (response) {
self.ServiceArea(response);
if (response.length === 1) {
self.ServiceAreaID(response[0].ServiceAreaID);
}
}, 'json');
}
});
// deptName is another representation of deptID
self.deptName = ko.computed(function() {
// I don't know whether your dept is observableArray or plain array
var depts = ko.unwrap(self.dept);
var currentOne = ko.utils.arrayFirst(depts, function(d) {
return d.DepartmentID == self.deptID();
});
return currentOne && currentOne.DepartmentName;
});
B) 모델을 변경하고 deptID를 캡처하지 말고 전체 deptSelected 개체를 캡처합니다.
//self.deptID = ko.observable();
self.deptSelected = ko.observable();
self.deptSelected.subscribe(function (newDept) { /* ajax */ });
// optionsText: 'DepartmentName' is enough, no need a mapping function.
<select class="span12" id="AssignedDepartment" name="AssignedDepartment"
data-bind="options: dept, optionsCaption: 'Select a department',
optionsText: 'DepartmentName', value: deptSelected"></select>
<!-- ko with: deptSelected -->
<span data-bind="text: DepartmentID"></span>
<span data-bind="text: DepartmentName"></span>
@Html.HiddenFor(m => m.Department, new { data_bind = "value: DepartmentName" })
@Html.HiddenFor(m => m.DepartmentCode, new { data_bind = "value: DepartmentID" })
<!-- /ko -->
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다