Skip to content

Instantly share code, notes, and snippets.

@bkardell
Last active December 26, 2015 14:19
Show Gist options
  • Save bkardell/7165293 to your computer and use it in GitHub Desktop.
Save bkardell/7165293 to your computer and use it in GitHub Desktop.

ElementControllers are really basic means of binding models with DOM and back and handling management of Views (different fragments of HTML inside the element being controlled) and interstitial states of those views. They can't handle complex relationships, and they don't have a whole templating solution wound up in them either. They don't infinitely shield your code in abstractions, but they keep it fairly clear and decoupled and they are really lightweight.

###Creating a ElementController You create a ElementController with an element...

var controller = new ElementController(document.body);

###Defining a named View (imperative/low level/not general case -- just explains underlying magic) Views are named and defined via .defineView:

// second arg can also be a reference to <hitch-view> element (see below)
controller.defineView(name, viewSerialization); 

###Defining several named Views (imperative)

// second arg can also be a reference to <hitch-viewspec> element (see below)
controller.defineViews(viewsSerialization); 

###Defining several named Views (imperative/netword)

controller.loadViewspec(url); 

###Defining named Views (declaratively) You can combine markup like the below with the above to provide a marriage between...

<!-- myViews.html -->
<hitch-viewspec>

    <hitch-view name="verifyName">
    	<form>
    	    <h1>What is your name?</h1>
	    	<div>
    			<input data-binding="name@value">
		    </div>
		    <button>Say Hello</button>
		    <button>Say Goodbye</button>
	    </form>
    </hitch-view>
    
    <hitch-view name="showMe">
        <h1><span data-binding="say@innerHTML"></span> <span data-binding="name@innerHTML"></span>!</h1>
    </hitch-view>
    
    <hitch-view name="error">
        <h1>Oh crap... Something went wrong!</h1>
        <div data-binding="error@innerHTML"></div>
    </hitch-view>
    
</hitch-viewspec>

###Configuring a View Define the imperative end of things by way of a controllerMixin which may contain entries corresponding to the named states that provide configuration data...

controller.configureView("verifyName", function () {
	// `this` is the `View` object
	
	// can be a plain object or a promise, it's managed for you...
	// {} is provided by default configuration 
	this.model = new DependencyHash({
        "person": {url: "/path/to/data/person", responseType: "json"}
    }).then(function(dependencies) {
        // you have an opportinity here to do stuff with N pieces of data to make them 1
       return dependencies.person; 
    });
    
    // activate is called on your behalf when you use controller.transitionTo (see below)...
    // his job is basically to build the viewModel
    // this.viewModel = model; is provided by default...
    this.activate = function () {
        // you have an opportunity to add calculated properties, etc...
       
        // you can mixin calculated properties
        Controller.mixin(this.viewModel, { calculated1: function () { return "whee"; }});
    };

    this.on("keypress", controller.rebind);
);

###Transitioning from one View to another... You can use the .transitionTo(string) method to move between named views - this causes model to be populated and .activate() to be called on that View.

controller.transitionTo("verifyName");

It is also possible to provide the model in transitionTo as a second argument, in this case, the argument supplants the model and set it rather than the one provided in .activate().

controller.transitionTo("verifyName", {"some": "data"});

###Bindings Binding to the DOM is expressed via the data-binding attribute and has a syntax of:

// Specify binding via the model property @ how you want to bind.
viewModelProperyName@binding[?;viewModelProperyName@binding...]

Where binding may be any of the following foms:

  • elementInstanceProperty
  • .className
  • [attributeName]

Examples...

  <div id="myView">
	<!-- gets the value of firstname from the `ViewModel` and sets the value property of this element -->
	<input data-binding="firstname@value">
	
	<!-- gets the value of greeting from the `ViewModel` and sets the innerHTML of this element -->	
	<div data-binding="greeting@innerHTML">
	
	<!-- 
	gets the value of isFoo from the `ViewModel` and sets the foo class of this element if its return value 
	is truthy, removes it if falsey
	-->
	<div data-binding="[email protected]">
	
	<!-- 
	gets the value of isFoo from the `ViewModel` and sets the foo class of this element if its return value 
	is truthy, removes it if falsey, does the inverse for bar
	-->
	<div data-binding="[email protected]||.bar">
	
	<!-- 
	gets the value of isNameLocked from the `ViewModel` and sets the disabled attribute of this element if its return value
	is truthy, removes it if falsey.
	-->
	<div data-binding="isNameLocked@[disabled]">
	
	
	<!-- 
	it is also possible to use lhs negation 
	-->
	<div data-binding="[email protected]">
  </div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment