【问题标题】:Kendo ListView: Add/Create not reflected until browser session is refreshedKendo ListView:在刷新浏览器会话之前不会反映添加/创建
【发布时间】:2021-02-19 17:59:36
【问题描述】:

我正在使用 MVC 和 Kendo (UI v2018.3.1017) ListView 来管理我称为“MaximoList”的列表。为了使列表对多个控制器可用,我利用了 MVC 提供的“TempData”对象。在创建(和销毁)时,我看到 MaximoList 对象正确地反映了更改。但是为了反映 UI 的变化,我必须刷新 (F5) (Chrome) 浏览器。

对控件的 CSHTML 引用相当简单:

    <div class="col-md-3">
      <div class="form-group">
        <label style="white-space: nowrap;">Maximo Id's</label>
        <a id="btnAddMaximoEntry" onclick=window.allIsos.addMaximoEntry() href="#" title='Add Maximo' style='margin-left: 8px'><i class='fa fa-upload'></i></a>
        <div class="" id="divMaximoList">
        </div>
      </div>
    </div>

控件的JS定义为:

function addMaximoListView(isoId, outageId) {
  maximoListDataSource = new kendo.data.DataSource({
    transport: {
      read: { url: "/request/GetMaximoList", type: "GET", dataType: "json", cache: false },
      create: { url: "/request/AddMaximoEntry", type: "Post", dataType: "json", cache: false },
      destroy: { url: "/request/DeleteMaximoEntry", type: "POST", dataType: "json", cache: false },
      update: {},
      parameterMap: function (data, type) {
        if (type == "read") { return { IsoId: isoId, OutageId: outageId }; }
        if (type == "create") { return { MaximoId: data.MaximoId }; }
        if (type == "destroy") { return { id: data.Id }; }
      },
      sortable: true,
      pageable: true,
    },
    requestEnd: function (e) {
      console.log(e.type);
      console.log(e.response);
    },
    columns: [
      { field: "Id", Title: "Id", width: "0px" },
      { field: "MaximoId", Title: "MaximoId", width: "50px" },
      { command: ["edit", "destroy"], title: "&nbsp;", width: "250px" }
    ],
    autoSync: false,
    schema: {
      model: {
        id: "Id",
        fields: {
          Id: { editable: false },
          MaximoId: { editable: true, type: "string" },
        }
      },
    },
  });
  var getTemplate = ""
    + "<div>"
    + "    <a onclick=window.allIsos.deleteMaximo(#:Id#) href='\\#'><i class='fa fa-trash'></i></a>"
    + '#:MaximoId#</div>';
  var editTemplate = ""
    + "<div>"
    + "  <input type='text' data-bind='value: MaximoId' name='MaximoId' required='required' />"
    + "  <div>"
    + "    <a class='k-button k-update-button' href='\\#'><span class='k-icon k-i-check'></span></a>"
    + "    <a class='k-button k-cancel-button' href='\\#'><span class='k-icon k-i-cancel'></span></a>"
    + "  </div>"
    + "</div>";
  $("#divMaximoList").kendoListView({
    template: kendo.template(getTemplate),
    editTemplate: kendo.template(editTemplate),
    dataSource: maximoListDataSource,
    pageSize: 5,
    dataBound: function (e) {
      console.log("ListView is bound and ready to render.");
    }
  });
};

将项目添加到列表的 JS 定义是:

var addMaximoEntry = function () {
  var listView = $("#divMaximoList").data("kendoListView");
  listView.add();
};

重新启动调试本地应用程序,这里是从 API/数据库公开测试数据的控件:

我点击了我的添加按钮,在接受输入之前,请注意为我的新 MaximoId 输入的值为“NotWorking”:

接受输入后,请注意控件添加了一个新条目,但它是原始条目之一的幻影:

但是在刷新页面 (F5) 后,请注意当 GET 触发从服务器端 TempData 对象拉取时,服务器正确接收到实际的“NotWorking”项目,并且更新的 TempData 对象被传递到 UI(其中包括新条目):

创建/添加的 API 方法如下 - 我将返回 UI,即更新后的 MaximoList 对象的 JSON 表示并使用该更新后的对象,刷新到 TempData["MaximoList"]:

[HttpPost, Route("AddMaximoEntry")]
public ActionResult AddMaximoEntry(string MaximoId)
{
  var ignoreCase = StringComparison.InvariantCultureIgnoreCase;
  try
  {
    List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();

    var maximoId = MaximoId;// unnecessary variable, but used for testing against multiple method confgurations

    var maximoEntry = new MaximoEntry();
    maximoEntry.MaximoId = maximoId;

    if (maximoList.Where(s => s.MaximoId.Equals(maximoEntry.MaximoId, ignoreCase)).FirstOrDefault() == null)
      maximoList.Add(maximoEntry);

    TempData["MaximoList"] = maximoList as List<MaximoEntry>;
    return Json(maximoList, JsonRequestBehavior.AllowGet);
  }
  catch (Exception ex)
  {
    var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
    return new JsonResult
    {
      Data = new
      {
        id = 0,
        Success = false,
        Msg = "Something went wrong while adding to the Maximo List. Please contact system support!"
      }
    };
  }
}

API GET 如下:

[HttpGet, Route("GetMaximoList")]
public ActionResult GetMaximoList(int IsoId, int OutageId)
{
  try
  {
    List<MaximoEntry> maximoList = ODataGetMaximoList(IsoId, OutageId);
    return Json(maximoList, JsonRequestBehavior.AllowGet);
  }
  catch (Exception ex)
  {
    var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
    return new JsonResult
    {
      Data = new
      {
        id = 0,
        Success = false,
        Msg = "Something went wrong while getting Maximo List. Please contact system support!"
      }
    };
  }
}

【问题讨论】:

    标签: asp.net-mvc listview kendo-ui tempdata transport


    【解决方案1】:

    最初,ADD(CREATE) 的 API 方法传回 Maximo 条目的整个列表(JSON 数组)。

    解决方案是只传回最初传递给 ADD(CREATE) 方法的 model 对象的更新版本,包括新分配的“id”值。新创建的条目将有一个负索引值,稍后我将在 MERGE 语句中的数据库级别使用该值(即主键的负值不应该存在于数据库表中)来同步数据库。

    如果还不清楚,我正在使用 TempData["MaximoList"] 对象来维护跨 API 控制器的 Kendo ListView 控件的状态。将控件状态保存到数据库(利用 TempData 对象)将在更通用的控制器方法中发生,该方法不管理 TempData 对象的状态(添加/删除/等)。

    我还重新设计了 DESTROY(删除)组件,以便仅在成功的 API 调用时从(UI)列表中删除已删除的项目,并通过删除一些不需要的控件集来清理 JS反映 TempData 对象的状态。

    我的 ADD 方法的 API 方法现在是:

    [HttpPost, Route("AddMaximoEntry")]
    public JsonResult AddMaximoEntry(MaximoEntry model)
    {
      var ignoreCase = StringComparison.InvariantCultureIgnoreCase;
      try
      {
        List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();
    
        var minId = maximoList.Where(w => w.id <= 0);
        model.id = minId.Count() == 0 ? -1 : minId.Select(s => s.id).Min() - 1;
    
        if (maximoList.Where(s => s.maximoId.Equals(model.maximoId, ignoreCase)).FirstOrDefault() == null)
          maximoList.Add(model);
    
        TempData["MaximoList"] = maximoList as List<MaximoEntry>;
        return Json(model, JsonRequestBehavior.AllowGet);
      }
      catch (Exception ex)
      {
        var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
        return new JsonResult
        {
          Data = new
          {
            Success = false,
            Msg = "Something went wrong while adding to the Maximo List. Please contact system support!"
          }
        };
      }
    }
    

    我还更新了我的 DELETE 方法,作为 HTTPDELETE 方法,并返回一个状态指示器来提醒调用 JS 操作结果:

    [HttpDelete, Route("DeleteMaximoEntry")]
    public JsonResult DeleteMaximoEntry(int id)
    {
      try
      {
        List<MaximoEntry> maximoList = TempData["MaximoList"] != null ? TempData["MaximoList"] as List<MaximoEntry> : new List<MaximoEntry>();
    
        var itemToRemove = maximoList.SingleOrDefault(r => r.id == id);
        if (itemToRemove != null)
          maximoList.Remove(itemToRemove);
    
        TempData["MaximoList"] = maximoList as List<MaximoEntry>;
    
        return Json(new { success = true, responseText = $"id {id} deleted from TempData object" });
      }
      catch (Exception ex)
      {
        var msg = $"Excepton: {ex.Message}. Inner Expection: {(ex.InnerException == null ? "N/A" : ex.InnerException.ToString())}";
        return new JsonResult
        {
          Data = new
          {
            Success = false,
            Msg = $"Something went wrong while deleteing Maximo Entry (id {id}). Please contact system support!"
          }
        };
      }
    }
    

    SELECT(READ)和CREATE(Add)的JS控件定义为:

    function addMaximoListView(isoId, outageId) {
      maximoListDataSource = new kendo.data.DataSource({
        transport: {
          batch: false,//default is false
          read: { dataType: "json", cache: false, type: "GET", url: "/request/GetMaximoList" },
          create: { dataType: "json", cache: false, type: "POST", url: "/request/AddMaximoEntry" },
          parameterMap: function (data, type) {
            if (type == "read") { return { IsoId: isoId, OutageId: outageId }; }
            if (type == "create") { return { model: data }; }
          },
        },
        requestEnd: function (e) {
          console.log(e.type);
          console.log(e.response);
        },
        autoSync: false,
        serverFiltering: true,
        schema: {
          model: {
            id: "id",
            fields: {
              maximoId: { editable: true, type: "string" },
            }
          },
        },
      });
      var getTemplate = ""
        + "<div>"
        + "  <a onclick=window.allIsos.deleteMaximo(#:id#) href='\\#'><i class='fa fa-trash'></i></a>"
        + "  #:maximoId#"
        + "</div > ";
      var editTemplate = ""
        + "<div>"
        + "  <input type='text' data-bind='value: maximoId' name='MaximoId' required='required' />"
        + "  <div>"
        + "    <a class='k-button k-update-button' href='\\#'><span class='k-icon k-i-check'></span></a>"
        + "    <a class='k-button k-cancel-button' href='\\#'><span class='k-icon k-i-cancel'></span></a>"
        + "  </div>"
        + "</div>";
    
      $("#divMaximoList").kendoListView({
        template: kendo.template(getTemplate),
        editTemplate: kendo.template(editTemplate),
        dataSource: maximoListDataSource,
        dataBound: function (e) {
          console.log("ListView is bound and ready to render.");
        }
      });
    };
    

    对于DESTROY(DELETE),我已经添加了这些JS方法(希望将这些元素嵌入到控件定义中):

    var deleteMaximo = function (id) {
      executeDeleteMaximo(id, "Are you sure you want to delete this Maximo entry?");
    }
    
    function executeDeleteMaximo(id, confirmMsg) {
      common.LoadingGif("#mainView", false);
      common.ConfirmDialog(true, confirmMsg,
        function (reason) {
          if (reason == "NO") {
            common.LoadingGif("#mainView", true);
            return false;
          }
          $.ajax({
            type: "DELETE",
            data: { id: id },
            url: "/request/DeleteMaximoEntry",
            success: function (response) {
              var data = response;
              if (data.success) {
                var myDataSource = $("#divMaximoList").data().kendoListView.dataSource;
                var item = myDataSource.get(id);//need a check before attempting remove
                myDataSource.remove(item);
    
              }
              common.LoadingGif("#mainView", true);
              window.scrollTo(0, 0);
            },
            error: function (jqXHR, textStatus, errorThrown) {
              var e = errorThrown;
            }
          });
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2020-11-04
      • 1970-01-01
      • 2020-12-02
      • 1970-01-01
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多