我正在ASP.NET MVC网站上为用户创建Profile。我有很多属性(复选框,下拉列表等),如:
我可以制作自己的模型来处理所有这些:
public class ProfileViewModel
{
public TimeZoneOptions TimeZone { get; set; }
public DstOptions Dst { get; set; } // Daylight Saving Time
public bool EmailSettings1 { get; set; }
public bool EmailSettings2 { get; set; }
// ...
public bool EmailSettings22 { get; set; }
}
我的视图模型属性不是彼此绑定的。所以,我不需要致电ModelState.IsValid
。看起来我的模型总是有效的。
如果我遵循在ASP.NET MVC中保存模型的标准方法,它将强制我的客户点击两次:
但我希望他们只需点击一下即可。就像在这个截图上一样:
我希望每个属性在用户点击时标记为“已保存更改”。 我希望用最少量的代码来实现这个目标。看起来很容易做到:
或
但我无法决定什么是更好的。在jQuery中,我可以直接使用DOM进行操作。但似乎淘汰赛可能更优雅,我可以使我的代码更易于维护。
我不知道如何使用knockout执行此操作,可能需要更新元素时需要某种绑定,如下所示:
<span data-bind="display-when-saved-for-property: EmailSettings1"></span>
???
也许有其他方法可以做到这一点。任何帮助都将受到高度赞赏。
答案 0 :(得分:3)
我认为它可以用knockout + jQuery实现。使用淘汰赛非常容易构建具有不断变化布局的应用程序(如您的情况)。在您的情况下,JQuery是异步请求所必需的。
所以,viewmodel:
var ViewModel = function(data) {
var self = this;
var _isCurrentSavingProp = null;
self.EmailSettings1 = ko.observable(data.EmailSettings1);
self.IsEmailSettings1Saved = ko.observable();
... another props
self.EmailSettings1.subscribe(function(val) {
isCurrentSavingProp = self.IsEmailSettings1Saved;
self.save();
});
... another subscribers
self.save = function() {
isCurrentSavingProp(false);
$.post(url, ko.toJSON(self), function() {
isCurrentSavingProp(true);
})
}
}
HTML:
<span data-bind="visible: IsEmailSettings1Saved" style="display: none"></span>
<input type="checkbox" data-bind="value: EmailSettings1" />
... etc..
答案 1 :(得分:1)
好的,你的模型必须是这样的。
public class MyModel
{
public bool? Friends { get; set; }
public bool? Photos { get; set; }
public string Car { get; set; }
}
您的控制器方法会接收模型的实例。只要您的ajax请求的数据名称与模型中属性的名称相匹配,它就会绑定。
public void UpdateValues(MyModel model)
{
if(model.Friends != null)
{
//Save
}
if (model.Photos != null)
{
//Save
}
if (model.Car != null)
{
//Save
}
}
让我们说你的HTML标记是这样的
<div id="checkbox-container">
<div>
<label>
<input type="checkbox" name="friends" />
My Friends</label>
</div>
<div>
<label><input type="checkbox" name="photos" />My Photos</label>
</div>
<select id="car-dropdown">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
</div>
这是jQuery ....
$('#checkbox-container input:checkbox').change(function () {
//Gets the property name we will bind
var field = $(this).attr("name");
var isChecked = $(this).prop("checked");
var data = {};
data[field] = isChecked;
requestBuilder(data);
});
//New method for our dropdown
$('#car-dropdown').change(function()
{
var data = {};
data['Car'] = $(this).val();
requestBuilder(data);
});
function requestBuilder(data)
{
//Ajax Request
$.ajax({
//Change url to match your controller
url:"/Controller/UpdateValues/",
data:data,
type:"POST",
success:function(response)
{
alert("Change Saved")
}
});
}
注意我们如何传递Name =“”属性。这与我们模型中的名称相匹配,因此它将绑定:)
如果您需要我扩展任何元素,请告诉我。我还为前端代码创建了一个jsfiddle - http://jsfiddle.net/8tKBx/
祝你好运!答案 2 :(得分:1)
我的理解是您拥有的用户配置列表将被呈现为checkbox
或dropdownlist
。
如果是这样,那么你是正确的,KnockoutJS是更加优雅的方式(我之前遇到了同样的问题,除了我有一个保存按钮,我很幸运)。让我们看看我们在这里有什么:
您的模型主要是bool
属性,毫无疑问您应该使用KnockoutJS mapping plugin。为什么?我们要做的就是:
view
HTML标记。view
时,发出AJAX请求以获取用户配置文件,然后使用mapping plugin
将返回的数据转换为ViewModel
并将其绑定到view
(所有这些都不需要自己编写ViewModel,这意味着如果服务器上的ViewModel发生了变化,我们只需要修改view
)。checkbox
或dropdownlist
添加change
事件处理程序(使用jQuery)。change
函数只需使用ViewModel
(仅一行代码)将绑定的mapping plugin
再次转换为JSON字符串要显示“已保存更改”消息,您只需传递对调用输入的引用,并使用一点点jQuery魔法附加您的消息。
的更新强>
你应该看起来像这样(或者可能比我的好):
var UserProfile;
$(document).ready(function() {
$('#ViewContainer input:checkbox').change(function (event) {
SaveUserProfile(event);
});
IntializeUserProfile();
});
function IntializeUserProfile() {
// Show spinner
$.ajax({
type: "POST",
url: URL_To_Get_User_Profile,
data: UserId, // in case of you need to pass data.
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
UserProfile = ko.mapping.fromJSON(data); //ko.mapping.fromJS($.parseJSON(msg));
ko.applyBindings(UserProfile, selector);
// Hide Spinner
}
});
}
function SaveUserProfile(event) {
// Show Spinner
var model = ko.toJSON(ko.mapping.toJS(UserProfile));
event = event || window.event;
target = event.target || event.srcElement;
$.ajax({
type: "POST",
url: URL_To_Save_UserProfile,
data: model,
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(data) {
// Hide Spinner
// here you have the caller input ==>target.
// for example, you can get it's parent to append your message
// or just show message in the page as notification.
}
});
}