好的,我已经充分希望在Google和SO上搜索。我已经被困在这3天了,无法弄清楚自己。
我有一个C#Hub,它返回Enumerable<RadicalTask>
。
我想创建一个内部包含其他模型的视图模型。我有这个:
ViewModel = {
Tasks: new TaskListModel(null),
User: new UserModel(null),
};
我做这样的绑定:
$.connection.hub.start().done(function () {
$.connection.taskHub.server.getTaskList().done(function (res) {
ViewModel.Tasks = ko.mapping.fromJS(res, TasksMappings);
$.connection.taskHub.server.getCurrentUser().done(function (ress) {
ViewModel.User = ko.mapping.fromJS(ress, UserMappings);
ko.applyBindings(ViewModel);
}).fail(function (error) {
console.error(error);
});
}).fail(function (error) {
console.error(error);
});
});
用户只是一个具有属性的类,如果需要也可以激进的任务我可以给你我的模型。
然后我想在模型上有其他功能,所以我这样做了:
var UserModel = function (data) {
ko.mapping.fromJS(data, {}, this);
self = this;
self.CanEdit = function () {
if (self.UserPermissions() == null) return false;
return self.UserPermissions().CanEdit();
};
self.CanReply = function () {
if (self.UserPermissions() == null) return false;
return self.UserPermissions().CanReply();
};
self.CanWork = function () {
if (self.UserPermissions() == null) return false;
return self.UserPermissions().CanWork();
};
self.CanStopWorking = function (taskID) {
if (self.User() == null) return false;
if (self.CurrentTask() == null) return false;
return self.CurrentTask().ID() == taskID;
};
self.CanStartWorking = function () {
if (self.User() == null) return false;
if (self.User().CurrentTask() != null) return false;
return true;
};
self.StartTask = function (task) {
self.hub.server.startTask(task.ID()).done(function (res) {
if (res) $('.bottom-right').notify({
message: {
text: 'You are working on task with id : ' + task.ID()
},
fadeOut: {
enabled: true,
delay: 2000
},
type: 'success'
}).show();
else $('.bottom-right').notify({
message: {
text: 'Failed to start working on task with id : ' + task.ID()
},
fadeOut: {
enabled: true,
delay: 2000
},
type: 'danger'
}).show();
});
};
self.StopTask = function (task) {
self.hub.server.stopTask(task.ID()).done(function (res) {
if (!res) {
$('.bottom-right').notify({
message: {
text: 'Failed to stop work on task with id :' + task.ID()
},
fadeOut: {
enabled: true,
delay: 2000
},
type: 'danger'
}).show();
} else {
$("#quickReply").modal().show();
}
});
$.connection.taskHub.client.UserUpdated = (function (res) {
ko.mapping.fromJS(res, {}, self);
});
};
};
/* Knockout ViewModel */
var TaskListModel = function (data) {
self = this;
if (data != null) {
ko.mapping.fromJS(data, {}, this);
alert(JSON.stringify(data));
}
self.selectedTask = ko.observable(null);
self.selectedID = ko.observable(-1);
self.selectTask = function (p) {
if (self.selectedID() == p.ID()) self.selectedID(-1); //Hide on click
else self.selectedID(p.ID());
self.selectedTask(p);
}; //Create the select method
self.Visible = function (p) {
return (p.ID() == self.selectedID());
};
self.quickReply = function (formElement) {
console.warn(formElement.taskId.value);
};
self.GetCSSClass = function (st) {
{
var statusC = "primary";
if (st == "Active") {
statusC = "primary";
} else if (st == "WaitingApproval") {
statusC = "success";
} else if (st == "OnHold") {
statusC = "danger";
} else if (st == "WaitingForInfo") {
statusC = "warning";
} else if (st == "Complete") {
statusC = "success";
}
return "label-" + statusC;
}
},
/*SignalR Callbacks*/
$.connection.taskHub.client.TaskListUpdated = (function (res) {
ko.mapping.fromJS(res, {}, self);
});
};
事情就是当我想要使用它时,它不断向我抛出函数未定义等错误。$root
,并且$parent
未定义。
<tbody data-bind="foreach: Items">
<tr data-bind="click: $parents[0].selectTask">
<td data-bind="text: $data.StatusText"></td>
<td data-bind="text: $data.ID"></td>
<td data-bind="text: $data.Title"></td>
<td data-bind="text: $data.Priority"></td>
<td data-bind="text: $data.Date"></td>
<td data-bind="text: $data.Creator.Name"></td>
<td data-bind="text: $data.UserAssigned.Name"></td>
</tr>
<tr data-bind="visible:true">
<td colspan="8">
<div>
<div class="well">
<table class="table" cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">
<tr>
<td>Title:</td>
<td data-bind="text:$data.Title"></td>
</tr>@*@if (Model.Task.ParentTask != null) {
<tr>
<td>Parent:</td>
<td><a href="www.google.com/" data-bind="text:$data.Title"></a>
</td>
</tr>}*@
<tr>
<td>Description:</td>
<td data-binding="text:$data.Description"></td>
</tr>
<tr>
<td>Creator:</td>
<td data-bind="text:$data.Creator.Name"></td>
</tr>
<tr>
<td>Status:</td>
<td data-bind="text:$data.StatusText"></td>
</tr>@*
<tr>
<td>Last Update:</td>
<td data-bind="text:$data.LastUpdate"></td>
</tr>
<tr>
<td>Total Time:</td>
<td data-bind="text:$data.TotalTime"></td>
</tr>*@
<tr>
<td>Test Name :</td>
<td data-bind="text: $data.UnitTestName"></td>
</tr>
<tr>
<td>Actions :</td>
<td>@*
<div data-bind="text: alert(JSON.stringify($root))"> <a class="btn btn-info" data-bind="attr : { href : '/Home/TaskDetails/' + $data.ID()}"> Go To Task</a>
<button class="btn btn-danger" data-bind="visible : $parent.U.CanStopWorking($data.ID()), click:$root.StopTask">Stop Task</button>
<button class="btn btn-success" data-bind="visible : $root.CanStartWorking, click:$root.StartTask">Start Task</button>
<button class="btn btn-primary " data-bind="visible: $root.User.CanReply" data-toggle="modal" data-target="#quickReply">QuickReply</button>
</div>*@</td>
</tr>
</table>
<div class="panel panel-primary">
<div class="panel-heading">Last Status Comments:</div>
<div class="panel-body" data-bind="foreach: $data.Comments">
<p><span class="label" data-bind="text:$data.StatusString, css : GetCSSClass($data.StatusString())"></span> <b data-bind="text: $data.CommentStamp"> </b> <span data-bind="text:$data.Text"></span>
</p>
</div>
</div>
</div>
</div>
</td>
</tr>
</tbody>
所以我很确定这里存在结构问题,但我不确定如何或从哪里开始。
工作流程如下:使用SignalR获取数据,使用knockout更新UI。
但我希望能够使用多个视图模型,而不必使用Bind(elementID) 所以我希望它封装在主视图模型中。
有人能说出错的地方吗?更好的想法,或只是告诉如何解决这个问题?
修改
好的我已经尝试改变我的模型的方式:
var ViewModel = {
Tasks: new TaskListModel(),
User: new UserModel()
};
$(function () {
//Load Data from server
$.connection.hub.start().done(function () {
$.connection.taskHub.server.getTaskList().done(function (res) {
ViewModel.Tasks.SetData(res);
$.connection.taskHub.server.getCurrentUser().done(function (ress) {
ViewModel.User.SetData(ress);
ko.applyBindings(ViewModel);
}).fail(function (error) {
console.error(error);
});
}).fail(function (error) {
console.error(error);
});
});
});
我的SetData
功能如下:
// in User model:
self.User = ko.mapping.fromJS(null);
self.SetData = function (data) {
ko.mapping.fromJS(data,{},self.User);
};
// in Task model:
self.Items = ko.mapping.fromJS(null);
self.SetData = function (data) {
ko.mapping.fromJS(data, {}, self.Items);
};
任务模型项被分配用户不是。
我不知道为什么会这样,如果我这样做
var v = ko.mapping(data);
我的v
确实已分配给用户。
真诚地,我完全没有想法。我错过了什么,不应该这么困难,不是吗?