Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working with Knockout.js components and webpack

I'm moving an existing knockout.js project (based on Knockout components and requirejs). I have a startup file with requires and it work. The script entry in the file is

<script src="app/require.config.js"></script>
 <script data-main="app/startup" src="bower_modules/requirejs/require.js"></script>

In changing from requirejs to webpack, my entry file is as follows

require("../src/app/startup");
document.write(require("raw!./base.html"));

base.html is the same as what is in the original html file and is defined as

<div>
  <side-bar></side-bar>
  <page-container></page-container>
</div>

The problem is that when I run the page, nothing happens. When I put a debugger in the startup.js file, it is actually hit so I know it is being called but there is nothing on the page but the base html. The components are not rendered.

How do I get this to work?

like image 283
ritcoder Avatar asked May 07 '15 02:05

ritcoder


1 Answers

Took inspiration from here.

There were a few things that I needed to do to get this to work

  1. Since the ko-component was using the requirejs text loaded, I had to add the npm package text-loader.
  2. Changed the component loader to not use requirejs. This was breaking the loading since the site was complaining about its inability to find the module.
  3. Knockout was called alright but at the time, the html has not been loaded. To solve this, I added the following to the end of my entry file $(document).ready(function(){ ko.applyBindings({}); });

Tested this with one of the components so I'll have to either do same for all or await a while for a better solution.

I've only modified the side-bar component as a test.

Content of entry.js

require("./../src/bower_modules/semantic/dist/semantic.css");
require("css!./../src/css/styles.css");
var ko = require("knockout");
var $ = require("jquery");
require("../src/app/startup");
require("components/side-bar/side-bar.js");

document.write(require("raw!./base.html"));

$(document).ready(function(){
    ko.applyBindings({});
});

Content of side-bar.js

define(["require", "exports", "knockout", "observations", "config", "viewManager", "db", "ko-mapping", "text!./side-bar.html"], function (require, exports, ko, observations, config, viewManager, db, koMapping) {
    var setting = db.first("settings");
    var functions = {
        scrollToHome: function () { return viewManager.scrollToHome(); }
    };
    exports.template = require("text!./side-bar.html");
    var viewModel = (function () {
        function viewModel(params) {
            this.height = ko.computed(function () { return observations.pageHeight(); });
            this.settings = config.sideBarSettings;
            this.inverted = ko.computed(function () { return setting.invertMenu() ? "inverted" : ""; });
        }
        viewModel.prototype.onClick = function (item) {
            //try processing using the item data
            if (item.view) {
                var raw = koMapping.toJS(item.view);
                config.controllers.page.insertPage(raw);
                return;
            }
            if (item.fn) {
                var fn = item.fn();
                if (!fn)
                    return; //this is for when it is not an observable but an actual function
                if (!functions[fn])
                    throw "Could not find side-bar function " + fn;
                functions[fn]();
                return;
            }
            throw "Sidebar item does not contain any executable action";
        };
        viewModel.prototype.dispose = function () {
            // This runs when the component is torn down. Put here any logic necessary to clean up,
            // for example cancelling setTimeouts or disposing Knockout subscriptions/computeds.
        };
        return viewModel;
    })();
    exports.viewModel = viewModel;

    console.log('inside sidebar');
    ko.components.register('side-bar', {
        template: require("text!./side-bar.html"),
        viewModel: {
            createViewModel: function(params, componentInfo){
                //debugger;
                console.log('yes');
                return new viewModel(params);
            }
        }
    })
});
like image 148
ritcoder Avatar answered Oct 18 '22 08:10

ritcoder