danyolgiax
danyolgiax

Reputation: 13086

Using nested Knockout.js components with RequireJs

I've a Knockout.js component that uses a nested pagination component like this:

TypeScript code

import ko = require("knockout");

class NetworkListViewModel {
    arrayValue = ko.observableArray<string>();
    currentPage = ko.observable<number>(0);
    totalItemCount = ko.observable<number>(0);

    constructor(params) {
        this.arrayValue = params.value
        this.currentPage(1);
        this.totalItemCount(params.totalItemCount);
    }
}

ko.components.register("network-list", {
    viewModel: NetworkListViewModel,
    template: { require: "text!components/network-list/network-list.html" }
});

HTML View

<div class="network-list" >
    <pagination params="CurrentPage: CurrentPage, TotalItemCount: TotalItemCount()"></pagination>
</div>

I've tryied to add a script to register it in RequireJs in this way:

HTML View

<div class="network-list" >
    <pagination params="CurrentPage: CurrentPage, TotalItemCount: TotalItemCount()"></pagination>
</div>
<script>
    require(["components/pagination/pagination"]);
</script>

but it doesn't works.

Registering those dependencies in the main view (index.cshtml) it works.

<div id="bindingSection">
    <network-list params="value: data, totalItemCount: totalItemCount()">  </network-list>
</div>

@section Scripts {
<script>
    require(['pages/home',
        "components/network-list/network-list",
        "components/pagination/pagination"
    ]);
</script>
}

Doing this implies that the developer have to know all child dependencies of each component (not simple in large projects). How can I instruct RequireJs to manage this nested component? Is there a way to move import responsability to the child component?

Upvotes: 0

Views: 162

Answers (1)

Quango
Quango

Reputation: 13448

The component for pagination is required for the network list, so the appropriate place to put the require is in the script for the networklist:

import ko = require("knockout");
import pagination = require("components/pagination/pagination");

class NetworkListViewModel {
   // code..

There is an issue that the TypeScript compiler will 'ignore' a require() statement if you don't actually reference the import in the code. You can work around this by adding a dummy line, e.g. var tmp = pagination;, or using the alternative import syntax, e.g.

/// <amd-dependency path="components/pagination/pagination" />

import ko = require("knockout");

class NetworkListViewModel {
   // code..

This approach will force TypeScript to load the module.

I use this sort of dependency a lot and it works very well. Often you only have a single require() in the page for the view model, all the rest is inherited.

Upvotes: 1

Related Questions