简体   繁体   English

用模型剔除计算列

[英]Knockout computed column with model

I have a model with the following property in my MVC C# solution 我的MVC C#解决方案中有一个具有以下属性的模型

public class RegistrationRequirementModel
{
    public string LoadIntent { get; set; }
    public string Francophone { get; set; }
    public string Gender { get; set; }

    public RegistrationRequirementModel(L09RegistrationRequirement requirement)
    {
        LoadIntent = requirement.LoadIntent;
        Francophone = requirement.Francophone;
        Gender = requirement.Gender;
    }
}

In my javascript I can call the model and display the data, however when it comes to using some computed function that is where it fails. 在我的JavaScript中,我可以调用模型并显示数据,但是在使用某些计算函数失败的情况下。

Javascript 使用Javascript

    var registrationRequirementModel = {
        frenchData:  ko.observable(""),
        genderData:  ko.observable(""),
        loadIntentData:  ko.observable(""),

        isMissingData: ko.computed(function () {
            if (this.frenchData() == "") { return true };
            if (this.genderData() == "") { return true };
            if (this.loadIntentData() == "") { return true };
            return false;
        },this),

    }

   $(document).ready(function () {

        ko.applyBindings(registrationRequirementModel, document.getElementById("RegistrationSurveyContent"));

        $.ajax({
            url: getStudentRegRequirementsUrl,
            type: "GET",
            contentType: jsonContentType,
            dataType: "json",
            success: function (data) {
                if (!account.handleInvalidSessionResponse(data)) {
                    registrationRequirementModel.frenchData(data.Francophone);
                    registrationRequirementModel.genderData(data.Gender);
                    registrationRequirementModel.loadIntentData(data.LoadIntent);
                }
            },
            error: function (jqXHR, textStatus, errorThrown) {
                if (jqXHR.status != 0)
                    $('#notificationHost').notificationCenter('addNotification', { message: "Unable to retrieve registration requirement.", type: "error" });
            }
        });
    });

Html HTML

<table style="width:100%">
    <tbody>
        <tr>
            <td data-bind="text: loadIntentData"></td>
            <td data-bind="text: frenchData"></td>
            <td data-bind="text: genderData"></td>
        </tr>
    </tbody>
</table>

The purpose is to show html if there is missing data. 目的是在缺少数据时显示html。 However when I activate this code, the computed column keep saying the frenchData is not a function. 但是,当我激活此代码时,计算列始终说frenchData不是函数。 My point would be able to use in my html data-bind="visible: isMissingData" . 我的观点将可以在我的html data-bind="visible: isMissingData" but unfortunately. 但不幸的是。 I can event read from my data. 我可以从数据中读取事件。

This is my call to the api 这是我给API的电话

 public async Task<JsonResult> GetRegistrationRequirementAsync()
 {
     string StudentID = CurrentUser.PersonId;
     try
     {
         var requirement = await ServiceClient.L09GetRegistrationRequirementAsync(StudentID);
         RegistrationRequirementModel registrationRequirementModel = new RegistrationRequirementModel(requirement);
         return Json(registrationRequirementModel, JsonRequestBehavior.AllowGet);
      }
      catch (Exception e)
      {}
}

The frenchData is not a function console error stems from the way that the KnockoutJS ViewModel is set up. frenchData is not a function控制台错误,其产生原因在于设置KnockoutJS ViewModel的方式。 In essence, the computed function isMissingData below the normal observables has a new inner scope context of this that does not reflect the same outer scope of the registrationRequirementModel object. 本质上,所计算的函数isMissingData低于正常可观测量具有一个新的内部范围上下文this不反映的相同的外部范围registrationRequirementModel对象。

在此处输入图片说明

To work around this, you should switch from using an object literal to a constructor function so that you can assign this ViewModel scope to a self/that variable which alleviates scope issues. 要解决此问题,您应该从使用object literal转换为constructor function以便可以this ViewModel范围分配给缓解范围问题的self/that变量。 Then instantiate your newly stored ViewModel via KO Apply Bindings that you will now have access to after AJAX success: 然后通过KO Apply Bindings实例化新存储的ViewModel,在AJAX成功后,您现在将可以访问它们:

function registrationRequirementModel() {
  var self = this;
  self.frenchData = ko.observable("");
  self.genderData = ko.observable("");
  self.loadIntentData = ko.observable("");

  self.isMissingData = ko.computed(function() {
    if (self.frenchData() == "") {
      return true
    };
    if (self.genderData() == "") {
      return true
    };
    if (self.loadIntentData() == "") {
      return true
    };
    return false;
  }, this);
}

$(document).ready(function() {
  var vm = new registrationRequirementModel();
  ko.applyBindings(vm, document.getElementById("RegistrationSurveyContent"));

  // replace with endpoint
  var jsonData = {
    Francophone: "Francophone",
    Gender: "Male",
    LoadIntent: "LoadIntent"
  };

  if (handleInvalidSessionResponse(jsonData)) {
    vm.frenchData(jsonData.Francophone);
    vm.genderData(jsonData.Gender);
    vm.loadIntentData(jsonData.LoadIntent);
  }
});

function handleInvalidSessionResponse(data) {
  if (typeof data !== "undefined") return true;
  return false;
}

Below is a mock JSFiddle of the scenario http://jsfiddle.net/ajxrw39m/3/ 以下是该场景的模拟JSFiddle http://jsfiddle.net/ajxrw39m/3/

When you're defining your viewmodel, this does not point to the newly created object, it points to whatever this is in the context you're creating it (probably window ). 当你定义您的视图模型, this并不指向新创建的对象,它指向任何this是你创建它(可能是上下文window )。

 var vm = { computedUsingThis: ko.computed(function() { return this; }, this) } console.log( vm.computedUsingThis() === vm, // false vm.computedUsingThis() === window // true ); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 

There are many ways to circumvent the issue. 有很多方法可以解决此问题。 You can use a constructor function and the new keyword, or create a factory method for the viewmodel: 您可以使用构造函数和new关键字,也可以为viewmodel创建工厂方法:

 const VM = () => { const a = ko.observable("a"); const b = ko.observable("b"); const ab = ko.pureComputed( () => a() + b() ); return { a, b, ab }; } const vm = VM(); vm.ab.subscribe(console.log); setTimeout( () => { vm.a("A"); }, 500 ) 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM