GithubHelp home page GithubHelp logo

johnculviner / fluentknockouthelpers Goto Github PK

View Code? Open in Web Editor NEW
57.0 14.0 31.0 2.62 MB

Strongly typed Knockout.js helpers for C# types demoed in a Durandal.js SPA

License: MIT License

C# 100.00%

fluentknockouthelpers's Introduction

Fluent Knockout Helpers Overview

Live Demo

FluentKnockoutHelpers

  • Painlessly generate Knockout syntax with strongly typed, fluent, lambda expression helpers similar to ASP.NET MVC
  • Rich intellisense and compiler support for syntax generation
  • Fluent syntax makes it a breeze to create custom helpers or extend whats built in
  • OSS alternative to ASP.NET MVC helpers: feel free to add optional features that everyone in the community can use and I'll merge your pull in ASAP!
  • Painlessly provides validation based on .NET types and DataAnnotations in a few lines of code for all current/future application types and changes
  • Client side JavaScript object factory (based on C# types) to create new items in for example, a list, with zero headaches or server traffic

Durandal.js

  • A single page application framework with Knockout.js baked in
  • Provides a FRAMEWORK to ORGANIZE your Controllers, ViewModels, and Views
  • Opinioned enough to allow for consitant file organization and efficiently avoids 'JavaScript hell'
  • Implements common application paradigms (ex. modals, message boxes etc.)
  • Flexible enough to be easily extended and built upon
  • Built on top of jQuery, Knockout & RequireJS so jQ Promises, MVVM, AMDs are baked in
  • Navigation, routing and screen state management are baked in.
  • Simple, effective app lifecycle events

Overview

Knockout.js allows for a very powerful MVVM style binding that makes it very easy to create rich web applications very quickly and with little code. One downside coming from the world of .NET and strong typing is that Knockout bindings use lots of "magic strings". This is where FluentKnockoutHelpers comes in as an attempt to bring all the goodness of ASP.NET MVC-like property expressions to Knockout with a fluent twist.

Instead of resorting to magic strings, no compile-time support and little intellisense when working with Knockout you can use FluentKnockoutHelpers to create property binding expressions just like how MVC does it for all the .NET defined types you are already using on the server to interact with your Knockout web client.

Durandal.js is a new framework that uses Knockout, jQuery, Require and Sammy that makes it very easy to create single page applications. It 'just works' with Knockout and feels very clean so I have created the Survey App using it. Also take note other than for the start page and WebAPI MVC isn't used at all for views. This seems pretty natural so far but time will tell as it is built out.

Take a look at Survey App demo to see a full demo using Durandal.js

#Quick Example Here is a quick example of what FluentKnockoutHelpers allows for using a classic Knocokout hello world example and an API endpoint to serve up the data (use of WebAPI isn't by any means required)

Person class defined in C# code

public class Person
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
}

API controller serving up a Person

public class PersonController : ApiController
{
  // GET api/person/5
  public Person Get(int id)
  {
    return _repo.People.First(x => x.PersonId == id)
  }
}

Knockout JavaScript ViewModel

var PersonViewModel = function(personId) {
	var self = this;

	self.person = ko.observable();

	//ctor
	$.getJSON('person/' + personId)
		.then(function(person) {
		
			//the ko.mapping plugin below converts the entire JSON
			//object graph into observables
			self.person(ko.mapping.fromJS(person));
		});
};

ko.applyBindings(new PersonViewModel(1));

CSHTML Helper Creation

Create a Strongly-Typed Helper for an Endpoint (Option A)

Here we create a Knockout helper bound the the WebAPI endpoint that we know the model is coming from. (Don't worry MVC controllers work fine too.) The expression isn't actually executed it just allows us to having strong typing. We must inform the FluentKnockoutHelpers what JavaScript ViewModel field our person is stored in, 'true' indicates it is observable. The 'this' below is an extension method off of WebPageBase meaning it works with MVC Razor views and "normal" Razor views alike.

<!-- The top of our CSHTML file -->
@{
  var person = this.KnockoutHelperForApi<PersonController>().Endpoint(api => api.Get(default(int)), "person", true);
}

Create a Strongly-Typed Helper for a Type (Option B)

Well maybe that felt a little weird or you aren't using WebAPI or MVC. No problemo, here is another approach that yields the same result. We still must inform the FluentKnockoutHelpers what JavaScript ViewModel field our person is stored in, 'true' indicates it is observable. The 'this' below is an extension method off of WebPageBase meaning it works with MVC Razor views and "normal" Razor views alike.

<!-- The top of our CSHTML file -->
@{
  var person = this.KnockoutHelperForType<Person>("person", true);
}

Putting it all together

Here is the bread and butter of FluentKnockoutHelpers. Since we have created a strongly-typed helper we now can use it to create strongly-typed expressions that at run time yield plain old Knockout code sans the magic strings. Since everyone likes to do their HTML in many different ways FluentKnockoutHelpers is flexible and extensible to accommodate many different ways of accomplishing the same markup result.

The markup we want to generate

    <div class="control-group">
		<label for="FirstName" class="control-label">
			First Name
		</label>
		<div class="controls">
			<input type="text" data-bind="value: person.FirstName" id="FirstName" />
		</div>
	</div>
    <div class="control-group">
		<label for="LastName" class="control-label">
			Last Name
		</label>
		<div class="controls">
			<input type="text" data-bind="value: person.LastName" id="LastName" />
		</div>
	</div>
    <h2>
        Hello,
        <!-- ko text: person.FirstName --><!-- /ko -->
        <!-- ko text: person.LastName --><!-- /ko -->
    </h2>

All out C# via FluentKnockoutHelpers (Option A)

We all love MVC (right?) lets pay it some hommage with a fluent twist! Note the DisplayNameFor(..) pulls from the [Display(..)] attribute. Don't worry there is a LabelFor(...) too..

<!-- Creation of the strongly-typed helper -->
    @{
      var person = this.KnockoutHelperForType<Person>("person", true);
    }
    
	<div class="control-group">
		@person.LabelFor(x => x.FirstName).Class("control-label")
		<div class="controls">
			@person.BoundTextBoxFor(x => x.FirstName)
		</div>
	</div>
	<div class="control-group">
		@person.LabelFor(x => x.LastName).Class("control-label")
		<div class="controls">
			@person.BoundTextBoxFor(x => x.LastName)
		</div>
	</div>
    <h2>
        Hello,
        @person.BoundTextFor(x => x.FirstName)
        @person.BoundTextFor(x => x.LastName)
    </h2>

Minimalistic markup generation via FluentKnockoutHelpers (Option B)

Minimilastic markup for those that like almost vanilla HTML and/or lots of typing

<!-- Creation of the strongly-typed helper -->
@{
  var person = this.KnockoutHelperForType<Person>("person", true);
}

<p>
	First name:
	<input type="text" class="fancy" @person.DataBind(db => db.Value(p => p.FirstName)) />
</p>
<p>
	Last name:
	<input type="text" class="fancy" @person.DataBind(db => db.Value(p => p.LastName))  /></p>
<h2>
	Hello,
	<!-- ko text: @person.EvalObservableFor(x => x.FirstName) --><!-- /ko -->
	<!-- ko text: @person.EvalObservableFor(x => x.LastName) --><!-- /ko -->
</h2>

Take a look at the demo app at /demo/SurveyApp.sln for an entire non-trival demo application that will cover almost all available Knockout bindings

fluentknockouthelpers's People

Contributors

holwerda avatar johnculviner avatar orthographic-pedant avatar zackpudil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fluentknockouthelpers's Issues

Exclude $type information from some requests

Hi John.

I've been using your framework in the last two months and I think it is great. One thing that I would like to improve is to serialize type information only when it is needed instead of serializing it in all requests.

As an exemple, in your demo App I think the request http://durandaldemo.apphb.com/api/color from the edit survey page is just used to fill the combobox. So in this case bringing type information from the server is just pure overhead.

I would like to hear your opinion on how to overcome this performance overhead.

Thanks,
Best regards.
Leonardo Silva.

Getting this to work with asp.net MVC

Hi John,
I am having issues getting this library to work with asp.net MVC, i have looked very well at the sample, added the core and Mvc libraries, changed my viewengine extension to cshtml, added the webconfig file to the views folder in my durandal app folder etc, etc. yet it still gives me a 404 thats says it cant find my .html files like shell.html. what do i do differently.
Thanks,
Joshua

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.