Нокаут вычисляемого столбца с моделью - PullRequest
0 голосов
/ 24 января 2019

У меня есть модель со следующим свойством в моем решении 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;
    }
}

В моем 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

<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>

Цель - показать HTML, если отсутствуют данные.Однако, когда я активирую этот код, вычисляемый столбец продолжает говорить, что frenchData не является функцией.Моя точка зрения будет в состоянии использовать в моем HTML data-bind="visible: isMissingData".но, к сожалению.Я могу прочитать событие из моих данных.

Это мой вызов 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)
      {}
}

Ответы [ 2 ]

0 голосов
/ 24 января 2019

Когда вы определяете свою модель представления, 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>

Есть много способов обойти эту проблему.Вы можете использовать функцию конструктора и ключевое слово new или создать фабричный метод для модели представления:

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>
0 голосов
/ 24 января 2019

Ошибка консоли frenchData is not a function связана со способом настройки KnockoutJS ViewModel. По сути, вычисляемая функция isMissingData ниже обычных наблюдаемых имеет новый контекст внутренней области this, который не отражает ту же внешнюю область объекта registrationRequirementModel.

enter image description here

Чтобы обойти эту проблему, вы должны переключиться с использования object literal на constructor function, чтобы можно было назначить область видимости this ViewModel для переменной self/that, которая устраняет проблемы с областью действия. Затем создайте экземпляр вашей новой сохраненной модели ViewModel с помощью KO Apply Bindings, к которым у вас теперь будет доступ после успеха 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;
}

Ниже приведен макет JSFiddle по сценарию http://jsfiddle.net/ajxrw39m/3/

...