Breeze and knockout quick start.
Posted: May 8, 2013 Filed under: .NET, JavaScript | Tags: breeze, knockout Leave a commentAn attempt at a bare minimum to get breeze and knockout going.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Create a new MVC4 web application web api project. This will bring in jQuery and knockout. | |
| Nuget install-package Breeze.WebApi. | |
| Add a dbcontext class in Models and a breeze api controller in Controllers. | |
| Add an html page with a view model and a view. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Linq; | |
| using System.Web.Http; | |
| using Breeze.WebApi; | |
| using MvcApplication1.Models; | |
| using Newtonsoft.Json.Linq; | |
| namespace MvcApplication1.Controllers | |
| { | |
| [BreezeController] | |
| public class FooController : ApiController | |
| { | |
| private readonly EFContextProvider<FooData> _ctx = new EFContextProvider<FooData>(); | |
| [HttpGet] | |
| public string Metadata() | |
| { | |
| return _ctx.Metadata(); | |
| } | |
| [HttpGet] | |
| public IQueryable<Foo> Foos() | |
| { | |
| return _ctx.Context.Foo; | |
| } | |
| [HttpPost] | |
| public SaveResult SaveChanges(JObject saveBundle) | |
| { | |
| return _ctx.SaveChanges(saveBundle); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Data.Entity; | |
| namespace MvcApplication1.Models | |
| { | |
| public class Foo | |
| { | |
| public int Id { get; set; } | |
| public String Name { get; set; } | |
| } | |
| public class FooData : DbContext | |
| { | |
| public DbSet<Foo> Foo { get; set; } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html xmlns="http://www.w3.org/1999/xhtml"> | |
| <head> | |
| <title></title> | |
| <script src="Scripts/jquery-1.8.2.min.js"></script> | |
| <script src="Scripts/knockout-2.2.0.js"></script> | |
| <script src="Scripts/q.min.js"></script> | |
| <script src="Scripts/breeze.min.js"></script> | |
| <script type="text/javascript"> | |
| var mgr = new breeze.EntityManager("breeze/Foo"); | |
| var Vm = function () { | |
| var items = ko.observableArray(); | |
| var item = ko.observable(); | |
| mgr.executeQuery(breeze.EntityQuery.from("Foos")) | |
| .then(function (val) { | |
| val.results.forEach(function (result) { | |
| items.push(result); | |
| }); | |
| }); | |
| function add() { | |
| items.push(mgr.createEntity("Foo", { Name: item() })); | |
| mgr.saveChanges(); | |
| item(""); | |
| } | |
| function remove(data) { | |
| data.entityAspect.setDeleted(); | |
| mgr.saveChanges(); | |
| items.remove(data); | |
| } | |
| return { | |
| items: items, | |
| item: item, | |
| add: add, | |
| remove: remove | |
| }; | |
| }; | |
| $(function () { | |
| ko.applyBindings(new Vm()); | |
| }); | |
| </script> | |
| </head> | |
| <body> | |
| <form data-bind="submit: add"> | |
| <input type="text" data-bind="value: item" /> | |
| <input type="submit" value="add" /> | |
| </form> | |
| <div data-bind="foreach: items"> | |
| <span data-bind="text: Name"></span> | |
| <input type="button" value="delete" data-bind="click: $parent.remove" /> | |
| <br /> | |
| </div> | |
| </body> | |
| </html> |
Knockout with jQuery UI
Posted: April 28, 2013 Filed under: JavaScript | Tags: jQuery UI, knockout.js 3 CommentsSample code to demonstrate trivial edits using knockout.js and jQuery UI dialog.
The main things to note are that all item properties are observable, and changes to an observable’s properties can be undone. Depends on Popup.js.
Updated to include localStorage. And to add another property to the model with no muss no fuss.
<head runat="server">
<title></title>
<link href="Content/themes/base/jquery.ui.all.css" rel="stylesheet" />
<script src="Scripts/jquery-2.0.0.min.js"></script>
<script src="Scripts/jquery-ui-1.10.2.min.js"></script>
<script src="Scripts/knockout-2.2.1.js"></script>
<script src="Scripts/knockout.mapping-latest.js"></script>
<script src="Scripts/Popup.js"></script>
<script type="text/javascript">
$(function () {
ko.applyBindings(new ViewModel);
});
function Storage(ctor) {
// Class to handle local storage for observable array with observable item properties.
function load() {
var items = [] // Something to return.
var data = JSON.parse(localStorage.getItem(ctor.name));
if (data) {
data.forEach(function (item) {
var obj = new ctor(); // Spin up one of what was specified.
$.extend(obj, item); // Pound in the properties.
items.push(ko.mapping.fromJS(obj)); // Make all properties live and push it.
});
}
return items;
}
function save(value) {
var items = [] // Something to save.
value.forEach(function (item) {
items.push(ko.mapping.toJS(item)); // Strip off the KO decor.
});
localStorage.setItem(ctor.name, JSON.stringify(items)); // Stringify it and save it.
}
// Return this interface.
return {
load : load,
save : save
};
}
function Statefull() {
// Class to handle saving and restoring observable properties.
var self = this; // Hang onto this to prevent ambiguity later on.
var state = []; // Empty bag to hold properties.
function backup() {
// Clear the array and add items to the bag.
state = [];
for (var prop in this) {
// Add only "descendant" properties that are observable.
if (!self.hasOwnProperty(prop) && ko.isObservable(this[prop]))
state.push({ name: prop, value: this[prop]() });
}
};
function restore() {
// Replace values with saved ones.
state.forEach(function (prop) {
this[prop.name](prop.value);
}, this);
};
// Return this interface.
return {
backup: backup,
restore: restore,
};
}
function Contact() {
// Plain old property bag.
this.firstName = "";
this.lastName = "";
this.email = "";
};
function ViewModel() {
// Class to handle adding and editing items.
// Uses jQuery UI dialog and KO bindings.
Contact.prototype = new Statefull; // Make Contact Statefull
var storage = new Storage(Contact); // localStorage thingy.
function newItem() {
// Create scratch object where all properties are observable.
return (ko.mapping.fromJS(new Contact));
};
function clearItem() {
// Clear out the item being tracked.
thing(newItem());
};
function add() {
// Opens the dialog to allow a new item to be added.
// Saves the item when OK button is pressed.
clearItem(); // Set the tracked item to be a new item.
popup.show(
{
ok: function () {
things.push(thing()); // Add the new item.
storage.save(things()); // Save all things.
clearItem(); // Clear the tracked item.
}
}, { title: Popup.Strings.New }
);
};
function edit(item) {
// Opens the dialog to allow an existing item to be modified.
item.backup(); // Save the items state.
thing(item); // Set tracked item to the exisitng item.
popup.show({
ok: function () {
storage.save(things()); // Save all things.
},
cancel: function () {
item.restore(); // on Cancel restore the items state.
}
}, { title: Popup.Strings.Edit }
);
};
// Set up working variables.
var popup = new Popup("#edit"); // Tie in the dialog.
var thing = ko.observable(newItem()); // The tracked item.
var things = ko.observableArray(storage.load()); // All items.
// Return this interface.
return {
thing: thing,
things: things,
add: add,
edit: edit
};
};
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<div data-bind="with: thing" id="edit">
First: <input type="text" data-bind="value: firstName" />
Last: <input type="text" data-bind="value: lastName" />
Email: <input type="text" data-bind="value: email" />
</div>
<button data-bind="click: add">Add</button>
<div data-bind="foreach: things">
<span data-bind="text: firstName"></span>
<span data-bind="text: lastName"></span>
<span data-bind="text: email"></span>
<a href="#" data-bind="click: $parent.edit">edit</a>
<br />
</div>
</div>
</form>
</body>
What is this and why use new?
Posted: April 28, 2013 Filed under: JavaScript | Tags: constructor, javascript, new Leave a commentGiven the function.
var foo = function(name) {this.name = name; return this;}
This code may not do what one might think it does.
var a = foo("a"); a.name;
var b = foo("b"); b.name;
a.name;
You can kind of see why by checking out what these return.
foo("a");
new foo("a");
This however works as one might expect.
var a = new foo("a"); a.name;
var b = new foo("b"); b.name;
a.name;