Knockoutjs嵌套的ViewModel / component与typescript的绑定不起作用

时间:2017-01-21 18:23:23

标签: typescript knockout.js web-component

我一直在努力尝试让viewModel中的viewModel在淘汰赛中工作。任何帮助将非常感激。我正在使用typescript并想要一个地址控件列表,每个控件都有自己的viewmodel。

该项目只与一个地址控件完美配合,但是当将控件添加到父容器视图模型并使用组件时,子视图模型始终为空(即{},如下面的警告语句所示):

这是我的app.ts,完整代码https://github.com/richbeales/knockout-test

///<reference path="../node_modules/retyped-knockout-tsd-ambient/knockout.d.ts"/>

import * as ko from 'knockout';
import {AddressViewModel, Address} from './components/paf-widget';

ko.components.register('paf-address', {
    viewModel: AddressViewModel, // { require: 'components/paf-widget' },
    template: { require: 'text!components/paf-widget.html' }
});

class AddressesViewModel {
    addressList: KnockoutObservableArray<AddressViewModel>;

    constructor() {
        this.addressList = ko.observableArray<AddressViewModel>();
    }

    addAddress = function () {
        alert(ko.toJSON(this)); // returns {"addressList":[{}]}

        var childVm = new AddressViewModel();
        alert(ko.toJSON(childVm)); // returns {}
        childVm.chosenAddress(new Address());
        childVm.chosenAddress().Organisation = "Test";
        alert(ko.toJSON(childVm)); // returns {}

        var a = new Address();
        a.AddressLine1 = "The Street";
        alert(ko.toJSON(a)); // returns {"AddressLine1":"The Street"}

        this.addressList.push(childVm);
    }
}

var vm = new AddressesViewModel();
ko.applyBindings(vm);

这是我的index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Bootstrap with jQuery and KnockoutJS</title>
    <link rel="stylesheet"
          href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"/>
    <link rel="stylesheet" href="css/style.css"/>
</head>
<body>

<header>

</header>

<h1>App</h1>

Choose an Address
 <pre data-bind="text: ko.toJSON(addressList, null, 2)"></pre>

<ul data-bind="foreach: {data: addressList, as: 'addrVm'}" style="list-style: none;">
    <li class="addressli">
        <pre data-bind="text: ko.toJSON(addrVm, null, 2)"></pre>
        <div data-bind="component: {name: 'paf-address', with: addrVm }"></div>
    </li>
</ul>
<button class="btn btn-primary" data-bind="click: addAddress">Add an address</button>

<footer>

</footer>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.2/require.min.js" data-main="js/app"></script>
<script src="require-config.js"></script>
</body>
</html>

1 个答案:

答案 0 :(得分:3)

你有这个奇怪的问题,因为你多次加载击倒并且不一致。

第一次直接在index.html中,然后在app.js中使用require.js。因此,AddressViewModel使用的ko实例与AddressesViewModel不同,这就是您看到这些奇怪的空对象的原因。

解决此问题的最简单方法是删除index.html中对KO的直接引用:

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>

并在paf-widget.ts中正确包含淘汰赛,并使用:

import * as ko from 'knockout';

注意:更改后,请确保您的浏览器缓存已清除并正确获取新代码。