通过Knockout中的属性访问复杂类型,js foreach绑定

时间:2013-03-14 20:01:50

标签: knockout.js

我无法理解如何使用给定数组项的属性的属性。

以下是我得到的JSON响应示例:

[{
"Id":"3bddaa55-5cae-4d9d-8c2f-3cff9a853aa0",
"ServiceRequestId":"00000000-0000-0000-0000-000000000000",
"AuthorizationRequestId":"48c73685-ee1e-4eea-8bf0-74320d37c80c",
"Quantity":0,
"TreatmentStartDate":null,
"Dosage":{"Id":"cbdbed9e-4c80-4f5a-8a4b-8185c24e45a0",
          "Value":13.4,
          "Unit":"Spiel mit mehr"},
"Medication":{"IsAutoApproveWhiteList":null,
              "IsPartB":null,"Id":"b0f0e31c-3467-4d73-9dd5-e806a20223a3",
              "Name":"Pills of Awesomeness",
              "Code":"J1100",
              "BrandName":"Awesome Pills",
              "GenericName":"Awesome",
              "UnitOfMeasure":"Pounds",
"Dosages":[{"Id":"dd6e7cfb-252c-46c1-815f-832f9501e9ce",
            "Value":100,
            "Unit":"Fart"},
            {"Id":"4dc88918-c359-41fd-9eb8-50699ba627fd",
             "Value":75.6,
             "Unit":"Ride wit me."}],
            "MedicationType":725060001,
            "AllowedDiagnoses":null},
"DirectionsForUse":{"Id":"9faba6ed-5a67-4b45-bedb-a49191274cc7",
                    "Name":"Do not eat sand",
                    "IsValidAsLoadingDose":false},
"Refills":0,
"RequiredRegimenMedicationId":null,
"OptionalRegimenMedicationId":null,
"NonRegimenMedicationId":null,
"RequiredRegimenMedicationDosingId":null,
"OptionalRegimenMedicationDosingId":null,
"NonRegimenMedicationDosingId":null,
"DoseType":725060000,
"TypeOfMedication":0,
"MedicationType":0,
"Bsa":null,
"MaximumDosage":null,
"MaximumDosageFormulaId":null,
"NotAutoApprovedReason":0}]

接下来是我要设置的代码:

<table>
    <thead>
        <tr>
            <th>Name</th>
            <th>Dose</th>
            <th>Directions For Use</th>
            <th>Treatment Start Date</th>
            <th>Qty</th>
            <th>Refills</th>
            <th>Purchase Type</th>
        </tr>
    </thead>
    <tbody data-bind="foreach: ServiceItems">
        <tr>
            <td><span data-bind="text: $root.Medication.DisplayName"></span></td>
            <td><span data-bind=""></span></td>
            <td><span data-bind=""></span></td>
            <td><span data-bind=""></span></td>
            <td><span data-bind="text: Quantity"></span></td>
            <td><span data-bind="text: Refills"></span></td>
            <td><span data-bind=""></span></td>
        </tr>
    </tbody>
</table>




@section Scripts
{
    <script type="text/javascript">

        function ServiceItem(data) {
            var self = this;

            self.TreatmentStartDate = ko.observable(data.TreatmentStartDate);
            self.ServiceRequestId = data.ServiceRequestId;
            self.DoseType = ko.observable(data.DoseType);
            self.Medication = ko.observable(data.Medication);
            self.Dosage = ko.observable(data.Dosage);
            self.DirectionForUse = ko.observable(data.DirectionForUse);
            self.RequiredRegimenMedicationId = ko.observable(data.RequiredRegimenMedicationId);
            self.RequiredRegimenMedicationDosingId = ko.observable(data.RequiredRegimenMedicationDosingId);
            self.OptionalRegimenMedicationId = ko.observable(data.OptionalRegimenMedicationId);
            self.OptionalRegimenMedicationDosingId = ko.observable(data.OptionalRegimenMedicationDosingId);
            self.NonRegimenMedicationId = ko.observable(data.NonRegimenMedicationId);
            self.NonRegimenMedicationDosingId = ko.observable(data.NonRegimenMedicationDosingId);
            self.Quantity = ko.observable(data.Quantity);
            self.Refills = ko.observable(data.Refills);
        }

        function Medication(data) {
            var self = this;

            self.Name = data.Name;
            self.Code = data.Code;
            self.BrandName = data.BrandName;
            self.GenericName = data.GenericName;
            self.UnitOrMeasure = data.UnitOrMeasure;
            self.Dosages = data.Dosages;
            self.MedicationTypes = data.MedicationTypes;
            self.AllowedDiagnoses = data.AllowedDiagnoses;

            self.DisplayName = ko.computed(function () {
                if (self.Name != null && self.Name != "") {
                    return self.Name;
                } else {
                    return self.BrandName;
                }
            });
        }

        function Dosage(data) {
            var self = this;

            self.Id = data.Id;
            self.Value = data.Value;
            self.unit = data.Unit;
        }

        function DirectionForUse(data) {
            var self = this;

            self.Id = data.Id;
            self.Name = data.Name;
            self.IsValidAsLoadingDose = data.IsValidAsLoadingDose;
        }

        function ServiceItemsViewModel() {
            var self = this;

            self.ServiceItems = ko.observableArray();

            //Operations
            self.add = function(item) {
                self.ServiceItems.add(item);
            };

            self.remove = function(item) {
                self.ServiceItems.remove(item);
            };
        }

        var viewModel = new ServiceItemsViewModel();

        $.getJSON('/Mapping/GetServiceItems', function (data) {
            ko.mapping.fromJS(data, {}, viewModel.ServiceItems);
        });

        ko.applyBindings(viewModel);

    </script>
}

我希望在foreach绑定运行期间在第一列中使用Medication计算方法。我没有正确调用的行是:

<td><span data-bind="text: $root.Medication.DisplayName"></span></td>

我在FireBugs控制台中收到的错误消息是:

  

错误:无法解析绑定。   消息:TypeError:$ root.Medication未定义;   绑定值:text:$ root.Medication.DisplayName

如何传播到Medication属性并正确触发该方法?

谢谢!

编辑:

<td><span data-bind="text: $root.Medication.DisplayName"></span></td>

更改为:

<td data-bind="text: Medication.DisplayName"></td>

我还在函数内部添加了一个警报,但它没有触发。

function Medication(data) {
        var self = this;

        self.Name = data.Name;
        self.Code = data.Code;
        self.BrandName = data.BrandName;
        self.GenericName = data.GenericName;
        self.UnitOrMeasure = data.UnitOrMeasure;
        self.Dosages = data.Dosages;
        self.MedicationTypes = data.MedicationTypes;
        self.AllowedDiagnoses = data.AllowedDiagnoses;

        self.DisplayName = ko.computed(function () {
            alert('Explode Please');
            if (self.Name != null && self.Name != "") {
                return self.Name;
            } else {
                return self.BrandName;
            }
        });
    }

当前结果不会产生错误,并且此表结果为:

Result of above EDIT changes

2 个答案:

答案 0 :(得分:2)

$root更改foreach绑定到网页视图模型的上下文:ServiceItemsViewModel。默认情况下,foreach中的上下文为ServiceItem。由于ServiceItem是上下文,而且它是包含Medication的视图模型,因此span的正确绑定是:<span data-bind="text: Medication.DisplayName"></span>

http://knockoutjs.com/documentation/foreach-binding.html

您还需要修复此行: self.Medication = ko.observable(data.Medication); 应该是:self.Medication = ko.observable(new Medication(data.Medication));

我怀疑它甚至需要是一个可观察的,但我不能确定不知道页面的其他行为。

绑定建议 我会像这样直接绑定到<td><td data-bind="text: Medication.DisplayName"/>

http://jsfiddle.net/5emCS/1/

答案 1 :(得分:1)

没关系,我想出了自己的问题。我使用$ root远远落后于我的项目链。感谢