Skip to content

Instantly share code, notes, and snippets.

@jacobslusser
Last active December 22, 2017 00:52
Show Gist options
  • Save jacobslusser/2d9210606a8ab64f3a4df7747ee40404 to your computer and use it in GitHub Desktop.
Save jacobslusser/2d9210606a8ab64f3a4df7747ee40404 to your computer and use it in GitHub Desktop.
A RequireJS plugin for loading and registering Knockout components/templates
// The component is required using the 'component!' plugin we created. This will load
// 'page1.html' and 'page1.js' and return 'page1.js' to us.
define(['knockout', 'component!page1'], function (ko, Page1) {
'use strict';
function App() {
var args = { name: 'Jacob' };
// Example of using the component binding with the automatically registered component
this.sampleComponent = ko.observable({
name: 'page1',
params: args
});
// Templates can also be used and are probably preferable because we have easy access
// to the view model if we want to programmatically call anything on the view model.
// i.e. sampleTemplate().data.yourFunction()
this.sampleTemplate = ko.observable({
name: 'page1',
data: new Page1(args)
});
this.init = function init() {
ko.applyBindings(this);
};
}
return new App();
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Knockout RequireJS Plugin</title>
</head>
<body>
<div data-bind="component: sampleComponent"></div>
<div data-bind="template: sampleTemplate"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.2/require.js" data-main="main.js" async></script>
</body>
</html>
(function () {
'use strict';
// A simple RequireJS plugin that will load a view and view model based on naming convention.
// Once loaded the view is added to the DOM so it can be used with KO templates and the view
// and view model are registered as a KO component.
define('component', ['jquery', 'knockout'], function ($, ko) {
return {
load: function (name, parentRequire, onload, config) {
parentRequire([name, 'text!' + name + '.html'], function (viewModel, view) {
// Add the view to the DOM
var template = '<script type="text/template" id="' + name + '">' + view + '</script>';
$('body').append(template);
// Register as a KO component
ko.components.register(name, {
viewModel: viewModel,
template: { element: name },
synchronous: true
});
onload(viewModel);
}, function (err) {
onload.error(err);
});
}
};
});
// Standard RequireJS stuff...
requirejs.config({
paths: {
'jquery': 'https://code.jquery.com/jquery-1.12.4',
'knockout': 'https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-debug',
'text': 'https://cdnjs.cloudflare.com/ajax/libs/require-text/2.0.12/text'
}
});
// Start the application
require(['app'], function (app) {
app.init();
});
}());
<div>
<h1>Welcome: <span data-bind="text: userName"></span></h1>
</div>
define(['knockout'], function (ko) {
'use strict';
function Page1(params) {
this.userName = ko.observable(params.name);
}
return Page1;
});
@jacobslusser
Copy link
Author

NOTE: I've offer additional explanations and how this approach solves several issues in the following knockout/knockout threads:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment