Day 1 of my 100DaysOfCode journey is over and I’ve already cheated a little bit…
In order to determine if I wanted to do this challenge, I had to lay a little bit of ground work in the form of fleshing out the app idea and making sure it was viable. On my Trello to-do list for Week 1, I had the proposal and outline as the first two days. Those are both done and I’ve already done the third day of Week 1 as well. I have setup the project and Github repo. Don’t worry, I expected the first week to be a little off-kilter, so that’s OK.
Let’s talk about the project setup
For this project, I set up an .Net Core blank solution and added a few projects to it. I like to start with a blank solution because it keeps all the namespaces nice and tidy.
The main project is a .Net Core Web App with MVC. This is where the Javascript, CSS, and web-server lives. The second project is a .Net Core class library. This project is designed to abstract the data fetching and pushing. Technically, this project is not needed, but since I plan to rip out the fake-data API later on, I wanted to plan ahead for that.
To create this setup
Open Visual Studio and click on Create a new project. On the next page, search for Blank Solution and click it. Then click Next, set the solution name and click Create.
Now that your solution is created, right-click on it in the Solution Explorer. Go to Add > New Project. Find ASP.Net Core Web Application. Click Next, fill in the details, and then click Create. Make sure to select Web Application (Model-View-Controller) then click Create again.
Follow similar steps to create the .Net Core Class Library.
Setting up LESS CSS pre-compiling
In order to make my CSS development a little more enjoyable, I’ve chosen to use LESS. LESS isn’t actually CSS, but it’s pretty close. Visual Studio does some magic with it to turn it into real CSS. I’ll get into that more later, but here’s how you set it up.
The first thing you’ll have to do is install the Web Compiled extension in Visual Studio. On the top toolbar, click on Extensions and then Manage Extensions. Look for Web Compiler:
Go ahead and install it, then restart Visual Studio.
At the root of the Mvc folder, create a LESS folder. Inside that folder, add a LESS file (right-click > Add > New Item… > LESS Style Sheet). Now, right-click on that folder, go to Web Compiler > Compile file. Now you will see a name.css and name.min.css file. Congratulations, you’ve compiled a LESS file into CSS. I’ll get into the imports and more complex stuff in a different post.
Javascript
For this project, I’ve chosen to use Knockoutjs with Requirejs for the front-end work. I like Knockoutjs because it works really well with .Net without a lot of extra setup and pre-ordained folder structures. Requirejs is used to help keep file sizes down and it allows me to store the knockoutjs html templates in their own files. This sounds like a lot so allow me to demonstrate.
In the wwwroot folder, I have created a js folder. Inside that folder, I’ve added a components folder with a dashboard folder to hold the dashboard component information.
I’ve also installed three packages: knockout, require, and require-text. This is done by right-clicking on the js folder and going to Add > Client-Side Library. Then search for the packages and install them. This completes the initial setup of the application. Now we need to configure knockout and require.
config.js
var require = { baseUrl: 'js/components', paths: { ko: '../knockout/knockout-latest', text: '../require-text/text' } };
This config file sets the baseUrl for all of our components to the js/components folder. This will make referencing them a little easier later on. The paths object defines the relative location of the knockout library and the text library. It is not required to add .js to the end of the filenames.
app.js
require(['ko'], function (ko) { ko.components.register('dashboard', { viewModel: { require: "dashboard/scripts/dashboard" }, template: { require: "text!dashboard/templates/dashboard.html" } }); ko.applyBindings(); });
This file calls the ko (knockout) scripts to register my components. “dashboard” is the component name, the viewModel (all of the javascript behind the html for the component) is located at “dashboard/scripts/dashboard” (again, the .js is not needed), and the template for this component is located at “dashboard/templates/dashboard.html”. Adding text! at the beginning tells require to parse the template as text, using the require-text library. Lastly, we will tell knockout to go ahead and do its thing with ko.applyBindings().
dashboard.js
define(['ko'], function (ko) { var koModel = function (params) { var self = this; self.title = "Test"; }; return koModel; });
This file uses require syntax to define and return the javascript function that we will use as the base for this module. We add a reference to this as self so that we can assign values to the model use the self. syntax.
dashboard.html
<div> <h2 data-bind="text:title"></h2> </div>
In dashboard.html, we have simple div and header tags. The h2 tag uses the data-bind syntax to display the title variable (self.title) from the dashboard.js file as text inside that tag.
Putting it all together
Before any of the preceding code does anything, we have to place the entry point for the scripts somewhere. I have chosen to wipe out everything in the default view created by Visual Studio (Views > Home > Index.cshtml). I have replaced it with the following:
<script type="text/javascript" src="~/js/config.js"></script> <script type="text/javascript" data-main="../app.js" src="~/js/require.js/require.js"></script> <div data-bind="component: 'dashboard'"></div>
First, we insert the config file to set our initial variables for requirejs. Then we call require.js with the data-main attribute pointing to our app.js file. Lastly, we bind a div to the dashboard component that is defined in app.js. That’s pretty much it.
Knockoutjs and Requirejs
Let’s talk a little bit about what these libraries do. Knockoutjs is a neat library that takes advantage of simple syntax and MVVM architecture for clean UI. When a value is updated, all the values (and related html tags) that rely on that value are re-rendered on the fly with the new information. This is nice because you don’t have to refresh the entire page to respond to a user selection and you don’t have to deal with complicated callback functions in traditional AJAX-based apps. It just does it automagically.
Requirejs is not *ahem* required to use knockoutjs, but it does do wonders for file size and modularity. Requirejs asynchronously loads files when they are needed, instead of bundling all of your components together into one large file. There is a lot more to it, but that’s beyond the scope of this post. Just know that requirejs is pretty well-supported and will make your life easier.