使用knockout asp .net mvc <table> </table>更新后刷新

时间:2014-08-13 11:40:37

标签: jquery asp.net-mvc knockout.js

我正在尝试从视图更新后刷新包含的角色行。 UI使用Knockout,后端是ASP NET MVC。我遇到的问题是,当我拨打GetRoles()时,我的更新信息没有刷新。但是,当我拨打self.Roles(data.RolesList)时,它会起作用。以下是我的实施。

视图:包含一个TABLE。单击TR时,将使用所选行的值填充输入。

@model ExpensesOrganiser4.ViewModels.RoleIndexViewModel

@section scripts{
@Scripts.Render("~/bundles/jqueryval")
@Scripts.Render("~/bundles/jqueryui")
@Styles.Render("~/Content/themes/base/css")
<script src="~/Scripts/knockout-2.1.0.js" type="text/javascript"></script>
<script src="~/Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
<script src="~/Scripts/Application/role.js" type="text/javascript"></script>
<script type="text/javascript">
    var kovm = new RoleVM(@Html.Raw(Json.Encode(Model)));
    ko.applyBindings(kovm);
</script>
@*<script type="text/javascript">
    RoleVM = ko.mapping.fromJS(@Html.Raw(Json.Encode(Model)));
</script>*@
}

<h2>Index</h2>

<p>
    <a data-bind="click: DisplayNew">Create New</a>
</p>

<!-- //TABLE containing rows of roles -->
<table border="1">
    <thead>
    <tr>
        <th>@Html.DisplayNameFor(model => model.Rvm.RoleID)</th>
        <th>@Html.DisplayNameFor(model => model.Rvm.RoleName)</th>
        <th>@Html.DisplayNameFor(model => model.Rvm.Description)</th>
        <th>@Html.DisplayNameFor(model => model.Rvm.ApplicationName)</th>
        <th>@Html.DisplayNameFor(model => model.Rvm.ApplicationDescription)</th>
        <th data-bind="visible: false"></th>
    </tr>
    </thead>

    <tbody data-bind="foreach: Roles">
    <tr data-bind="click: $root.GetSelectedRole" id="updtr">
        <td><span data-bind="text: RoleID"></span></td>
        <td><span data-bind="text: RoleName"></span></td>
        <td><span data-bind="text: Description"></span></td>
        <td><span data-bind="text: ApplicationName"></span></td>
        <td><span data-bind="text: ApplicationDescription"></span></td>
        <td data-bind="visible: false"><span data-bind="text: ApplicationID"></span></td>
    </tr>
    </tbody>
</table>
<!-- //END TABLE containing rows of roles -->

<!-- INPUTS populated when <TR> is clicked --->
<table data-bind="visible: ReadOnlyMode">
    <tr>
        <td><label for="RoleID">Role ID:</label></td>
        <td><input data-bind="value: RoleID" type="text" id="RoleID" /></td>
    </tr>
    <tr>
         <td><label for="RoleName">Role Name:</label></td>
         <td><input data-bind="value: RoleName" type="text" id="RoleName" /></td>
    </tr>
    <tr>
        <td><label for="Description">Role Description:</label></td>
        <td><input data-bind="value: Description" type="text" id="Description" /></td>
    </tr>
    <tr>
    <td><label for="ApplicationName">Application:</label></td>
    <!--<td>@Html.DropDownList("cboApplicationName", Model.ApplicationsSelectList, new Dictionary<string, object> {{ "data-bind", "value: ApplicationID"}})</td>-->
    <td><select data-bind="options: ApplicationsList, optionsText: 'AppName', optionsValue: 'AppID', value: ApplicationID" id="cboApplications"></select></td>
</tr>
<tr>
    <td><label for="ApplicationDescription">Application Description:</label></td>
    <td><input data-bind="value: SelectedApplication" type="text" id="ApplicationDescription" /></td>
</tr>
</table>

<button data-bind="visible: DisplayUpdateRoleButton, click: UpdateRole" id="btnUpdate">Update</button>
<button data-bind="visible: DisplayDeleteRoleButton" id="btnDelete">Delete</button>


<div id="dialog-confirm" title="Success">Success.</div>  

Knockout的定义:刷新方法function GetRoles()thrownerrorSyntaxError: Unexpected token <

var self; //declare self outside the view model logic. 

var RoleVM = function (data) {

self = this;

ko.mapping.fromJS(data, {}, self);

self.EditFields = ko.observable(false);
self.ReadOnlyMode = ko.observable(true);
self.DisplayEditRoleButton = ko.observable(true);
self.DisplayUpdateRoleButton = ko.observable(false);
self.DisplayDeleteRoleButton = ko.observable(false);
self.Roles = ko.observableArray(data.RolesList);
self.ApplicationsList = ko.observableArray(data.ApplicationsList);

self.RoleID = ko.observable();
self.RoleName = ko.observable();
self.Description = ko.observable();
self.ApplicationName = ko.observable();
self.ApplicationDescription = ko.observable();
self.ApplicationID = ko.observable();
self.SelectedApplication = ko.observable("");
self.ApplicationID.subscribe(function (value) {
    self.SelectedApplication(self.ApplicationsList()[value - 1].AppDesc);
});


self.GetSelectedRole = function (role) {
    self.RoleID(role.RoleID);
    self.RoleName(role.RoleName);
    self.Description(role.Description);
    self.ApplicationName(role.ApplicationName);
    self.ApplicationDescription(role.ApplicationDescription);
    self.ApplicationID(role.ApplicationID);
    self.DisplayUpdateRoleButton(true);
    self.DisplayDeleteRoleButton(true);
};

self.UpdateRole = function () {
    UpdateSelectedRole();
};

self.DisplayNew = function () {
    self.RoleID("");
    self.RoleName("");
    self.Description("");
    self.DisplayDeleteRoleButton(false);
};
};

//HERE. This is not working
function GetRoles() {
debugger;
$.ajax({
    cache: false,
    type: "GET",
    url: "/Roles",
    dataType: "JSON",
    success: function (vm) {
        debugger;
        console.log(vm);
        self.Roles(vm.RolesList);   //put response in self.Roles Observable array
    },
    error: function (xhr, ajaxOptions, thrownError) {
        alert("Failed to retrieve roles. " + "xhr.status: " + xhr.status + "thrownError: " + thrownError);
        //console.log(JSON.stringify(xhr));
        console.log(xhr.responseText);
        //console.log("AJAX error: " + ajaxOptions + ' : ' + thrownError);
    }
});
}

function UpdatedRoleInfo() {
this.RoleID;
this.RoleName;
this.RoleDescription;
this.ApplicationID;
}

function UpdateSelectedRole() {
var updatedRoleInfo = new UpdatedRoleInfo();

updatedRoleInfo.RoleID = self.RoleID();
updatedRoleInfo.RoleName = self.RoleName();
updatedRoleInfo.Description = self.Description();
updatedRoleInfo.ApplicationID = self.ApplicationID();
//updatedRoleInfo.ApplicationID = $("#cboApplications").val();

var url = "/Roles/Edit";

$.ajax({
    cache: false,
    type: "POST",
    url: "/Roles/Edit",
    data: updatedRoleInfo,
    success: function (data, textStatus) {
        UpdateRoleComplete(data);
        GetRoles();                    //Fails when I call this.
        //self.Roles(data.RolesList);  //Works when I call this.
    },
    error: function (xhr, ajaxOptions, thrownError) {
        alert("Failed to update. " + "xhr.status: " + xhr.status + "xhr.responseText: " + xhr.responseText);
    }
});
}

function UpdateRoleComplete(result) {
self.EditFields(false);
self.ReadOnlyMode(true);
self.DisplayEditRoleButton(true);
self.DisplayUpdateRoleButton(true);
//self.OriginalRoleName(result.ViewModel.RoleName);
//self.OriginalDescription(result.ViewModel.Description);

$("#dialog-confirm").dialog("open");
}


$("#dialog-confirm").dialog({
autoOpen: false,
resizable: false,
modal: true,
draggable: true,
width: 300,
buttons: {
    "OK": function () {
        $(this).dialog("close");
    }
}
});

MVC:

 public ActionResult Index()
 {
        RoleIndexViewModel viewModel = new RoleIndexViewModel();
        Roles r = new Roles();

        viewModel = r.CreateRoleIndexViewModel();

        return View(viewModel);
 }

[HttpPost]
public ActionResult Edit(RoleViewModel rvm)
{
        RoleIndexViewModel viewModel = new RoleIndexViewModel();
        Roles r = new Roles();

        if (ModelState.IsValid)
        {
            using (db)
            {
                tblRole role = db.tblRoles.Single(t => t.RoleID == rvm.RoleID);
                role.RoleName = rvm.RoleName;
                role.Description = rvm.Description;
                role.ApplicationID = rvm.ApplicationID;

                db.ObjectStateManager.ChangeObjectState(role, EntityState.Modified);
                db.SaveChanges();
            }

            viewModel = r.CreateRoleIndexViewModel();
        }

        return Json(viewModel, JsonRequestBehavior.AllowGet);
}

问题是由嵌套的AJAX调用引起的,即在UpdateSelectedRole()及其中GetRoles()吗?

由于

2 个答案:

答案 0 :(得分:0)

在你的ajax调用中首先清除roles数组然后像这样传递新的结果

self.Roles([]);
self.Roles(vm.RolesList);

同时更改GetRoles功能

self.GetRoles = () {
    // your code here
}

答案 1 :(得分:0)

因为self.Roles不是您要设置的函数中的全局/。

您可以进行以下更改,看看它是否有效?

更改

function UpdateSelectedRole() {
var updatedRoleInfo = new UpdatedRoleInfo();

updatedRoleInfo.RoleID = self.RoleID();
updatedRoleInfo.RoleName = self.RoleName();
updatedRoleInfo.Description = self.Description();
updatedRoleInfo.ApplicationID = self.ApplicationID();
//updatedRoleInfo.ApplicationID = $("#cboApplications").val();

var url = "/Roles/Edit";

$.ajax({
    cache: false,
    type: "POST",
    url: "/Roles/Edit",
    data: updatedRoleInfo,
    success: function (data, textStatus) {
        UpdateRoleComplete(data);
        GetRoles().success(function(data){
             self.Roles(data.RolesList);
        });

        //self.Roles(data.RolesList);  //Works when I call this.
    },
    error: function (xhr, ajaxOptions, thrownError) {
        alert("Failed to update. " + "xhr.status: " + xhr.status + "xhr.responseText: " + xhr.responseText);
    }
});
}

function GetRoles() {
return $.ajax({
    cache: false,
    type: "GET",
    url: "/Roles",
    dataType: "JSON"
});
}

GetRoles返回我在UpdateSelectedRole中解析的promise并填充了self.Roles