ko.observableArray不接受TypeScript中的数组类型的数组

时间:2017-03-17 19:05:00

标签: knockout.js typescript2.0

通过TypeScript运行Knockout教程以更好地理解它,我收到一个错误:“JavaScript运行时错误:初始化可观察数组时传递的参数必须是数组,或者为null,或者是未定义的。” 尝试了一些事情,这是我目前的地方,当然我错过了一些东西。我的主要目的是更好地理解TypeScript中的ObservableArrays。失败在TS代码的第25行。 'initialMeal'参数包含数组对象,但'meal'属性拒绝它。

/// <reference path="typings/jquery/jquery.d.ts" />
/// <reference path="typings/knockout/knockout.d.ts" />

module Home {
    export class Index {
        name: KnockoutObservable<string>;
        availableMeals: any[];
        meal: KnockoutObservableArray<InitialMeal>;
        seats: KnockoutObservableArray<any>;

        constructor() {
            let self = this;

            // Non-editable catalog data - would come from the server
            self.availableMeals = [
                { mealName: "Standard (sandwich)", price: 0 },
                { mealName: "Premium (lobster)", price: 34.95 },
                { mealName: "Ultimate (whole zebra)", price: 290 }
            ];
        }

        seatReservation(name: string, initialMeal: InitialMeal): void {
            let self = this;
            self.name = ko.observable(name);
            self.meal = ko.observableArray(initialMeal);
        }

        reservationsViewModel() {
            let self = this;

            // Editable data
            self.seats = ko.observableArray([
                self.seatReservation("Bob", self.availableMeals[1]),
                self.seatReservation("Stan", self.availableMeals[0])
            ]);
        }
    }

    interface InitialMeal extends Array<any> {
        mealName: string;
        price: number;
    }
}

$(document).ready(function () {
    let vm = new Home.Index();
    ko.applyBindings(vm.reservationsViewModel());
});
<div class="row">
    <div class="col-md-12">
        <table>
            <thead>
                <tr>
                    <th>Passenger name</th>
                    <th>Meal</th>
                    <th>Surcharge</th>
                    <th></th>
                </tr>
            </thead>
            <!-- Todo: Generate table body -->
            <tbody data-bind="foreach: seats">
                <tr>
                    <td data-bind="text: name"></td>
                    <td data-bind="text: meal().mealName"></td>
                    <td data-bind="text: meal().price"></td>
                </tr>
            </tbody>
        </table>
    </div>
</div>

1 个答案:

答案 0 :(得分:0)

似乎在2013年之前没有很多TypeScript 2 / Knockout的东西,但我确实设法让它工作。我重写了我的TS文件以获得更好的命名空间(将其视为MVC控制器),一旦我这样做,真正的罪魁祸首似乎是我调用数组元素的方式,因为TypeScript改变了Knockout期望你这样做的方式,显然。通过Knockout教程here,您可以将膳食名称和价格传递给数据绑定:meal()。mealName&amp;餐()的价格。但是,当从TS工作时,我需要将膳食作为命名空间的一部分而不是函数( meal()。mealName meal.mealName ),这是我的主要问题。我还将ko.applyBindings移动到视图中。希望这能帮助像我一样陷入困境的其他人。 调整后的代码是:

2 1 4 1 1 2 4 3 4 2
/// <reference path="typings/jquery/jquery.d.ts" />
/// <reference path="typings/knockout/knockout.d.ts" />
/// <reference path="typings/knockout.mapping/knockout.mapping.d.ts" />

module Index {

	// Class to represent a row in the seat reservations grid
	class SeatReservation {
		name: string;
		meal: KnockoutObservable<any>;

		constructor(name: string, initialMeal: any) {
			this.name = name;
			this.meal = initialMeal;
		};
	}

	export class ReservationsViewModel {

		seats: KnockoutObservableArray<any>;

		// Non-editable catalog data - would come from the server
		availableMeals = [
			{ mealName: "Standard (sandwich)", price: 0 },
			{ mealName: "Premium (lobster)", price: 34.95 },
			{ mealName: "Ultimate (whole zebra)", price: 290 }
		];

		constructor() {
			//Editable data
			this.seats = ko.observableArray([
				new SeatReservation("Steve", this.availableMeals[1]),
				new SeatReservation("Bert", this.availableMeals[2])
			]);
		}
	}
}