Skip to content
Nubgrammer
Menu
  • Home
  • Contact Me
Menu
knockout example

Creating a Knockout.js project on Codepen

Posted on May 9, 2021May 9, 2021 by Tyler Sells

This one is going to be about creating a knockout.js project on Codepen. Knockout.js has long fallen from the internet’s good graces but it’s still a very useful library that is much easier to grasp, write, and publish than React.js.

First, the Demo

Apparently, you can’t embed Codepen projects… so here’s the link: Knockout.js Template Project (codepen.io)

What I’ve done is setup an environment that uses a few different tools to make life easy. I’m using require.js, less.js, pug.js, and knockout.js. Codepen automatically handles the less and pug conversions for you.

Why less and pug?

Less is a preprocessor for CSS. One big reason to use a preprocessor is that you can separate your styles into separate files. For example, any theme-related color styles can be stored in a colors.less file and any typography related styles can be stored in a typography.less file. For larger projects, having this separation is extremely helpful. There are many other reasons to use a preprocessor but native CSS is starting to catch up and make them irrelevant. We aren’t there yet though.

Pug is also a preprocessor, but for HTML. I like it because the syntax is much quicker to write than HTML. See below:

Pug:

.card
  img(data-bind="attr:{src:img}")
  .name(data-bind="text:name")
  .email(data-bind="text:email")
button(data-bind="click:updateData") Reload Data

Processed HTML:

<div class="card"><img data-bind="attr:{src:img}"/>
  <div class="name" data-bind="text:name"></div>
  <div class="email" data-bind="text:email"></div>
</div>
<button data-bind="click:updateData">Reload Data</button>

So, Knockout and Require?

Knockout.js is strictly a data-binding library. I set a variable in javascript and then I tell a DOM element to display the value of that variable. That element will update any time that variable updates. On its own, it can do a lot of neat things but when you couple it with require.js, it feels a lot more like working with true components.

Require.js is an asynchronous module loader. With some configuration, you can dynamically load javascript files when and if you need them. In terms of what it actually does, it appends script elements to the head element in your app. Using the require-text.js library, you can include HTML files in a similar fashion. Combined, these two features help modularize Knockout.js.

Setting up Require

To start, you need a config file, the require.js library, and an app.js file. Put them in the body of your index page like so (reminder, this is pug):

    script(type="text/javascript",src="./js/config.js")
    script(type="text/javascript",data-main="app.js",src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js")

This is the config.js file:

var require = {
    baseUrl: '/js',
    paths: {
        ko: 'https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.0/knockout-min',
        text: 'https://cdnjs.cloudflare.com/ajax/libs/require-text/2.0.12/text.min'
    }
};

It simply contains an object with a few properties. baseUrl is the relative path to all of your javascript files. The paths property tells us where to find the knockout and require-text script files when you need them. I’m using CDNs here but you can use local files as well.

app.js:

const app = {};
require(['ko'], function (ko) {
    app.model = function(){
      
    }
    ko.components.register('home', {
        viewModel: { require: "js/home.js" },
        template: { require: "text!../templates/home.html" }
    });
    ko.applyBindings();

});

This file gets called in the require.js setup. This is the entry point into your application. I’ve registered a component called ‘home’. the viewModel property grabs the javascript file and the template property grabs the HTML template for that viewModel. Now, anytime I want the home component to show up, I call it like this:

In the index file:

div(data-bind="component: 'home'")

To recap, this is what the full index.pug file looks like (the fontawesome cdn is just something I like to use in pretty much everything):

doctype html
html
  head
    link(rel='stylesheet',type="text/css", href='css/main.processed.css')
    script(src="https://kit.fontawesome.com/ec16337fc0.js", crossorigin="anonymous")
  body
    script(type="text/javascript",src="./js/config.js")
    script(type="text/javascript",data-main="app.js",src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js")
    div(data-bind="component: 'home'")

The Components

In the project, I’ve created a home component. It requires a little bit of funky require.js syntax, but the short version is that I’m creating an object that handles default values related to parameters, calling a data API, and assigning observables.

define(['ko'], function (ko) {
    app.home = function (params) {

        var self = this;
        self.defaults = new defaults(params);
        self.getData = ()=>{
          fetch("https://randomuser.me/api/")
          .then(response => response.json())
          .then(json => {
            console.log(json)
            self.img(json.results[0].picture.large);
            self.name(json.results[0].name.first+" "+json.results[0].name.last);
            self.email(json.results[0].email);
          })
        };
        self.img = self.defaults.img;
        self.name = self.defaults.name;
        self.email = self.defaults.email;
        self.updateData = ()=>{
          self.getData();
        }
        self.getData();
    };
    var defaults = function (params) {
        var self = this;
        if(params==null) params = {};
       self.img = (params.img!=null)?params.img:ko.observable("");
        self.name = (params.name!=null)?params.name:ko.observable("Empty");
       
        self.email = (params.email!=null)?params.email:ko.observable("empty");
        return self;
    }

    return app.home;
});

Using the data-bind attribute, I can tell certain HTML elements what I want them to display. This is the home.pug file that is tied to the home knockout model:

.card
  img(data-bind="attr:{src:img}")
  .name(data-bind="text:name")
  .email(data-bind="text:email")
button(data-bind="click:updateData") Reload Data

There is a less file involved as well, but I just made it to make the demo look pretty. You can use any CSS preprocessor or vanilla CSS.

Final Folder Structure

  • css
    • main.less
  • imgs
    • backgrounds.jpg
  • js
    • app.js
    • config.js
    • home.js
  • templates
    • home.pug
  • index.pug

In the end, your folder layout can be whatever you want it to be, as long as it makes sense without thinking about it too much. I’ve seen hundreds of different ways of organizing projects across many different languages and frameworks. This is the one that speaks to me the most.

Author: Tyler Sells

Github

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • More
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to email a link to a friend (Opens in new window) Email
  • Click to share on Reddit (Opens in new window) Reddit

Like this:

Like Loading...

3 thoughts on “Creating a Knockout.js project on Codepen”

  1. Working at Walmart says:
    November 12, 2022 at 6:21 pm

    Good to know!

    Reply
  2. KazkzrdLak says:
    March 8, 2023 at 2:39 pm

    thank you very much

    Reply
  3. whoiscall says:
    August 2, 2023 at 11:42 am

    Good luck!

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Follow me on Twitter

My Tweets

Github Repos

vtsells (Tyler Sells)

Tyler Sells

vtsells
http://www.nubgrammer.com
Joined on Jun 21, 2017
9 Public Repositories
100DaysOfCode
embers
MultiSelect
MVC-Project-Start
nubgrammer.com
PermIT
Spray
vtsells.github.io
Wizard
0 Public Gists

Categories

  • #100DaysOfCode (4)
  • ASP.NET (7)
  • ASP.NET Core (1)
  • ASP.NET MVC (3)
  • CSS (4)
  • General (13)
  • JS (3)
  • LESS (2)
  • Snippets (4)
  • Tools (4)
  • Tutorials (9)

Recent Posts

  • Creating a Knockout.js project on Codepen
  • 100DaysOfCode Day 3 – A State of Mind
  • 100DaysOfCode Day 2 – The Building Blocks
  • 100DaysOfCode Day 1 (Sort of cheated already)
  • Committing to #100DaysOfCode
© 2025 Nubgrammer | Powered by Superbs Personal Blog theme
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies.
Do not sell my personal information.
Cookie SettingsAccept
Manage consent

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
CookieDurationDescription
cookielawinfo-checkbox-analytics11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional11 monthsThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policy11 monthsThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytics
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Advertisement
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
Others
Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.
SAVE & ACCEPT
%d

    Privacy Policy