Initial KnockoutSpa template

This commit is contained in:
SteveSandersonMS
2016-03-08 12:16:22 +00:00
parent 7d7e974b5f
commit bbdbb449d5
45 changed files with 2609 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
<div class='container-fluid'>
<div class='row'>
<div class='col-sm-3'>
<nav-menu params='route: route'></nav-menu>
</div>
<div class='col-sm-9' data-bind='component: { name: route().page, params: route }'></div>
</div>
</div>

View File

@@ -0,0 +1,8 @@
import * as ko from 'knockout';
import * as router from '../../router';
class AppLayoutViewModel {
public route = router.instance().currentRoute;
}
export default { viewModel: AppLayoutViewModel, template: require('./app-layout.html') };

View File

@@ -0,0 +1,7 @@
<h2>Counter</h2>
<p>This is a simple example of a Knockout component.</p>
<p>Current count: <strong data-bind='text: currentCount'></strong></p>
<button data-bind='click: incrementCounter'>Increment</button>

View File

@@ -0,0 +1,12 @@
import * as ko from 'knockout';
class CounterExampleViewModel {
public currentCount = ko.observable(0);
public incrementCounter() {
let prevCount = this.currentCount();
this.currentCount(prevCount + 1);
}
}
export default { viewModel: CounterExampleViewModel, template: require('./counter-example.html') };

View File

@@ -0,0 +1,24 @@
<h1>Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
<p data-bind='ifnot: forecasts'><em>Loading...</em></p>
<table class='table' data-bind='if: forecasts'>
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody data-bind='foreach: forecasts'>
<tr>
<td data-bind='text: dateFormatted'></td>
<td data-bind='text: temperatureC'></td>
<td data-bind='text: temperatureF'></td>
<td data-bind='text: summary'></td>
</tr>
</tbody>
</table>

View File

@@ -0,0 +1,22 @@
import * as ko from 'knockout';
interface WeatherForecast {
dateFormatted: string;
temperatureC: number;
temperatureF: number;
summary: string;
}
class FetchDataViewModel {
public forecasts = ko.observableArray<WeatherForecast>();
constructor() {
fetch('/api/SampleData/WeatherForecasts')
.then(response => response.json())
.then((data: WeatherForecast[]) => {
this.forecasts(data);
});
}
}
export default { viewModel: FetchDataViewModel, template: require('./fetch-data.html') };

View File

@@ -0,0 +1,15 @@
<h1>Hello, world!</h1>
<p>Welcome to your new single-page application, built with:</p>
<ul>
<li><a href='https://get.asp.net/'>ASP.NET Core</a> and <a href='https://msdn.microsoft.com/en-us/library/67ef8sbd.aspx'>C#</a> for cross-platform server-side code</li>
<li><a href='http://knockoutjs.com/'>Knockout.js</a> and <a href='http://www.typescriptlang.org/'>TypeScript</a> for client-side code</li>
<li><a href='https://webpack.github.io/'>Webpack</a> for building and bundling client-side resources</li>
<li><a href='http://getbootstrap.com/'>Bootstrap</a> for layout and styling</li>
</ul>
<p>To help you get started, we've also set up:</p>
<ul>
<li><strong>Client-side navigation</strong>. For example, click <em>Counter</em> then <em>Back</em> to return here.</li>
<li><strong>Webpack dev middleware</strong>. In development mode, there's no need to run the <code>webpack</code> build tool. Your client-side resources are dynamically built on demand. Updates are available as soon as you modify any file.</li>
<li><strong>Hot module replacement</strong>. In development mode, you don't even need to reload the page after making most changes. Within seconds of saving changes to files, your Knockout app will be rebuilt and a new instance injected is into the page.</li>
<li><strong>Efficient production builds</strong>. In production mode, development-time features are disabled, and the <code>webpack</code> build tool produces minified static CSS and JavaScript files.</li>
</ul>

View File

@@ -0,0 +1,6 @@
import * as ko from 'knockout';
class HomePageViewModel {
}
export default { viewModel: HomePageViewModel, template: require('./home-page.html') };

View File

@@ -0,0 +1,33 @@
<div class='main-nav'>
<div class='navbar navbar-inverse'>
<div class='navbar-header'>
<button type='button' class='navbar-toggle' data-toggle='collapse' data-target='.navbar-collapse'>
<span class='sr-only'>Toggle navigation</span>
<span class='icon-bar'></span>
<span class='icon-bar'></span>
<span class='icon-bar'></span>
</button>
<a class='navbar-brand' href='#'>WebApplicationBasic</a>
</div>
<div class='clearfix'></div>
<div class='navbar-collapse collapse'>
<ul class='nav navbar-nav'>
<li>
<a class='navbar-brand' href='#' data-bind='css: { active: route().page === "home-page" }'>
<span class='glyphicon glyphicon-home'></span> Home
</a>
</li>
<li>
<a class='navbar-brand' href='#counter' data-bind='css: { active: route().page === "counter-example" }'>
<span class='glyphicon glyphicon-education'></span> Counter
</a>
</li>
<li>
<a class='navbar-brand' href='#fetch-data' data-bind='css: { active: route().page === "fetch-data" }'>
<span class='glyphicon glyphicon-th-list'></span> Fetch data
</a>
</li>
</ul>
</div>
</div>
</div>

View File

@@ -0,0 +1,19 @@
import * as ko from 'knockout';
import { Route } from '../../router';
interface NavMenuParams {
route: KnockoutObservable<Route>;
}
class NavMenuViewModel {
public route: KnockoutObservable<Route>;
constructor(params: NavMenuParams) {
// This viewmodel doesn't do anything except pass through the 'route' parameter to the view.
// You could remove this viewmodel entirely, and define 'nav-menu' as a template-only component.
// But in most apps, you'll want some viewmodel logic to determine what navigation options appear.
this.route = params.route;
}
}
export default { viewModel: NavMenuViewModel, template: require('./nav-menu.html') };