Setting a value in Controller from Visualforce Page is taking too long - salesforce

I'm using Visualforce Page to display some selection fields, and based on the selections I'm updating my list.
<apex:form>
<div class="map-controls">
<div class="map-selects">
<apex:selectList value="{!state}" multiselect="false" size="1">
<apex:selectOptions value="{!states}"></apex:selectOptions>
<apex:actionSupport event="onchange" rerender="countyList" />
</apex:selectList>
<apex:selectList value="{!county}" multiselect="false" size="1" id="countyList">
<apex:selectOptions value="{!counties}"></apex:selectOptions>
</apex:selectList>
</div>
<div class="map-search">
<apex:commandButton value="Search" action="{!test}" rerender="productlistpanel" status="status" />
</div>
<div class="radio-btns">
<apex:selectRadio value="{!type}">
<apex:selectOptions value="{!types}" />
</apex:selectRadio>
</div>
</div>
</apex:form>
Basically what I'm trying to do here is, when user selects the State, County and Type upon clicking the commandButton, the product list will be rendered.
<apex:outputPanel id="productlistpanel">
<div class="splide" role="group">
<div class="splide__track">
<ul class="splide__list">
<apex:repeat value="{!products}" var="productKey" id="theRepeat">
<!-- REPEAT CONTENT -->
</apex:repeat>
</ul>
</div>
</div>
<script>
document.dispatchEvent(new CustomEvent("splideTest", { "detail": 'TEST' }));
</script>
</apex:outputPanel>
And this is my controller.
public List<SelectOption> getTypes() {
RecordTypeInfo TYPE1 = Schema.SObjectType.Product2.getRecordTypeInfosByDeveloperName().get('TYPE1');
RecordTypeInfo TYPE2 = Schema.SObjectType.Product2.getRecordTypeInfosByDeveloperName().get('TYPE2');
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption(TYPE1.getRecordTypeId(), 'TYPE1'));
options.add(new SelectOption(TYPE2.getRecordTypeId(), 'TYPE2'));
return options;
}
public List<SelectOption> getStates() {
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('All', 'All'));
List<State__c> states = [SELECT Id,
Name
FROM State__c];
for (State__c s : states) {
options.add(new SelectOption(s.Name, s.Name));
}
return options;
}
public List<SelectOption> getCounties() {
List<SelectOption> options = new List<SelectOption>();
options.add(new SelectOption('All', 'All'));
List<County__c> counties = new List<County__c>();
if (state != null && state != 'ALL') {
counties = [SELECT Id,
State__c,
Name
FROM County__c
WHERE State__r.Name = :state];
}
for (County__c c : counties) {
options.add(new SelectOption(c.Name, c.Name));
}
return options;
}
public PageReference test() {
return null;
}
public String state { get; set; }
public String county { get; set; }
public String type { get; set; }
public Map<Id, WRAPPER> productList { get; set; }
public Map<Id, WRAPPER> getProducts() {
try {
// CREATE QUERY
query += String.isNotBlank(state) && state != 'ALL' ? ' AND State__c = \'' + state + '\'' : '';
query += String.isNotBlank(county) && county != 'ALL' ? ' AND County__c = \'' + county + '\'' : '';
query += String.isNotBlank(type) ? ' AND RecordTypeId = \'' + type + '\'' : '';
query += ' ORDER BY Name ASC';
System.debug('query ' + query);
List<Product2> productList = (List<Product2>)database.query(query);
for (Product2 prod : productList) {
// CREATE LIST
}
return returnMap;
} catch (Exception ex) {
ApexPages.Message msg = new ApexPages.Message(ApexPages.Severity.Error, ex.getMessage());
ApexPages.addMessage(msg);
return null;
}
}
My problem is when I select the type and hit Search; the type is not available right away. I can see the rerender is being executed and at the logs I see that type is not saved. I have to click Search button again to see the Type selected as I wanted it to be.
I usually use Lightning Web Component and I don't deal with this kind of problem but unfortunately, I have to use VF Page for this implementation.
I could not locate any work-around so far, I tried to understand the delay, but it seems like it is not a common issue. I assume it is a design issue on my end. I couldn't locate why setting the value is not fast enough.
Does that happen to you, or do you have any suggestions for it?

You could cheat, write it in LWC and then use "Lightning Out" to display it. Saves the hassle of eventually rewriting it ;)
I suspect part of it is that only 1st picklist has apex:actionSupport.
You swallow the exception (maybe there's an issue with the query) and use addMessage - but for it to truly show you need <apex:pageMessages id="messages" /> tag and then add it to your rerender (rerender="productlistpanel,messages")
Your "type" picklist radio is the only one without fallback "ALL". I suspect in UI it apppears to have type1 selected as 1st entry but really the value is null because you didn't initalise it in controller? See if it behaves better if you explicitly set it in constructor for example.
Risko of soql injection (could use bind variables, even in dynamic soql), you could read about <apex:actionRegion> for such partial form submits. Shameless plug: https://salesforce.stackexchange.com/a/22216/799

Related

How to create a good custom DropDownList / ComboBox item in Blazor?

I want to use multiple ComboBox-Styled-Items on my Blazor-Server-App. My working code for this looks like this:
#page "/dropdownlist"
<h3>DropDownList - ComboBox</h3>
<select class="form-control col-6" #onchange="#(x => OnSelChange(x.Value.ToString()))">
<option value="">--SelectName--</option>
#foreach (var test in TestModelsLst)
{
<option value=#test.Id>#test.Name</option>
}
</select>
#if (SelectedTestModel != null)
{
<p>Sel TestModel-Obj.Name: #SelectedTestModel.Name</p>
}
#code {
public TestModel SelectedTestModel;
public void OnSelChange(string guidAsString)
{
SelectedTestModel = TestModelsLst.FirstOrDefault(x => x.Id.ToString() == guidAsString);
}
//---------------
public List<TestModel> TestModelsLst = new List<TestModel>
{
new TestModel("Jonny"),
new TestModel("Sarah"),
new TestModel("Tom")
};
public class TestModel
{
public Guid Id { get; set; }
public string Name { get; set; }
public TestModel(string name)
{
Id = Guid.NewGuid();
Name = name;
}
}
}
Questions:
1.
Is there a way to pass the Class-Obj. instead of passing Guid->string->SearchinLst -> select Obj.
e.g.: <option value=#test> #test.Name </option> (without the valueStuff)
2.
If my code is okay. The one thing that bothers me, is that I can't figur out to use a placeholder="--SelectName--" as I did in EditForms. In my solution right now user can select the option --SelectName--.
Thx
Is there a way to pass the Class-Obj. instead of passing Guid->string->SearchinLst -> select Obj. e.g.:
#test.Name (without the valueStuff)
Nope. The value property of the option element cannot be an object.
If my code is okay. The one thing that bothers me, is that I can't figur out to use a placeholder="--SelectName--" as I did in EditForms.
In my solution right now user can select the option --SelectName--.
If I understand correctly, the following might solve it (see attributes of --SelectName-- option) ...
<select class="form-control col-6" #onchange="#(x => OnSelChange(x.Value.ToString()))">
<option value="" disabled selected hidden>--SelectName--</option>
#foreach (var test in TestModelsLst)
{
<option value=#test.Id>#test.Name</option>
}
</select>

Episerver create page programmatically

I am using this code
var parent = ContentReference.StartPage;
IContentRepository contentRepository = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IContentRepository>();
PageData myPage = contentRepository.GetDefault<LoginPage>(parent);
myPage.PageName = "My new page";
var page = contentRepository.GetChildren<LoginPage>(parent).FirstOrDefault(name => name.Name == myPage.Name);
if (page == null)
contentRepository.Save(myPage, EPiServer.DataAccess.SaveAction.Publish);
to create a page programatically. The thing is I am not sure where to put this code?
I don't want to show LoginPage which is page type to show in the list in the admin/edit panel as I want to create only one page under that page type. Maybe there is another way where I can just create a stand alone page and don't have to create the page type or maybe use an already made page type.
This is the code for my page type
[ContentType(DisplayName = "Custom Login Page", GUID = "c0d358c3-4789-4e53-bef3-6ce20efecaeb", Description = "")]
public class LoginPage : StandardPage
{
/*
[CultureSpecific]
[Display(
Name = "Main body",
Description = "The main body will be shown in the main content area of the page, using the XHTML-editor you can insert for example text, images and tables.",
GroupName = SystemTabNames.Content,
Order = 1)]
public virtual XhtmlString MainBody { get; set; }
*/
}
Then I am creating a model like this
public class LoginModel : PageViewModel<LoginPage>
{
public LoginFormPostbackData LoginPostbackData { get; set; } = new LoginFormPostbackData();
public LoginModel(LoginPage currentPage)
: base(currentPage)
{
}
public string Message { get; set; }
}
public class LoginFormPostbackData
{
public string Username { get; set; }
public string Password { get; set; }
public bool RememberMe { get; set; }
public string ReturnUrl { get; set; }
}
And my controller looks like this
public ActionResult Index(LoginPage currentPage, [FromUri]string ReturnUrl)
{
var model = new LoginModel(currentPage);
model.LoginPostbackData.ReturnUrl = ReturnUrl;
return View(model);
}
Do you think there is another way to do it? I will also show my login view
#using EPiServer.Globalization
#model LoginModel
<h1 #Html.EditAttributes(x =>
x.CurrentPage.PageName)>#Model.CurrentPage.PageName</h1>
<p class="introduction" #Html.EditAttributes(x =>
x.CurrentPage.MetaDescription)>#Model.CurrentPage.MetaDescription</p>
<div class="row">
<div class="span8 clearfix" #Html.EditAttributes(x =>
x.CurrentPage.MainBody)>
#Html.DisplayFor(m => m.CurrentPage.MainBody)
</div>
#if (!User.Identity.IsAuthenticated &&
!User.IsInRole("rystadEnergyCustomer"))
{
<div class="row">
#using (Html.BeginForm("Post", null, new { language = ContentLanguage.PreferredCulture.Name }))
{
<div class="logo"></div>
#Html.AntiForgeryToken()
<h2 class="form-signin-heading">Log in</h2>
#Html.LabelFor(m => m.LoginPostbackData.Username, new { #class = "sr-only" })
#Html.TextBoxFor(m => m.LoginPostbackData.Username, new { #class = "form-control", autofocus = "autofocus" })
#Html.LabelFor(m => m.LoginPostbackData.Password, new { #class = "sr-only" })
#Html.PasswordFor(m => m.LoginPostbackData.Password, new { #class = "form-control" })
<div class="checkbox">
<label>
#Html.CheckBoxFor(m => m.LoginPostbackData.RememberMe)
#Html.DisplayNameFor(m => m.LoginPostbackData.RememberMe)
</label>
</div>
#Html.HiddenFor(m => m.LoginPostbackData.ReturnUrl, "/login-customers")
<input type="submit" value="Log in" class="btn btn-lg btn-primary btn-block" />
}
#Html.DisplayFor(m => m.Message)
</div>
}
else
{
<span>Welcome #User.Identity.Name</span>
#Html.ActionLink("Logout", "Logout", "LoginPage", null, null);
}
I think you're misunderstanding some of the Episerver concepts.
If you don't want it to be a page in Episerver, you shouldn't use PageController, page types, or templates. Instead, just use a standard controller and view to create your login page.
Otherwise, you do have to create a page of type LoginPage, which will be visible in the page tree. No need to create it programmatically, you can just add the page manually and then hide the LoginPage type from edit mode to avoid editors creating additional login pages.

angularjs bootstrap typeahead return child

My input binds to object line.product however typeahead is returning the list of pairs of products and supplier. The current ps.product as ps.product.code for ps in getProductSupplierRefList($viewValue) does not return the expected product.
<input ng-model="line.product"
class=" form-control"
typeahead="ps.product as ps.product.code for ps in getProductSupplierRefList($viewValue)"
typeahead-loading="isLoading"
typeahead-on-select="productSupplierSelected($item, line)"
typeahead-template-url="productSupplierRefList.html"/>
getProductSupplierRefList calls webapi and return a list of ProductSupplierRefModel:
public class ProductSupplierRefModel
{
public ProductRefModel Product { get; set; }
public SupplierRefModel Supplier { get; set; }
}
The product code is expected in text control:
Any suggestion pls?
use typeahead-input-formatter to show the code. looks like ps.product as ps.product.code is not working???
<input ng-model="line.product"
type="text"
class=" form-control"
ng-keyup="getProductSupplierRefList($event)"
typeahead="ps.product as ps.product.code for ps in filterProductSuppliers"
typeahead-loading="isLoading"
typeahead-input-formatter="formatProduct($model)"
typeahead-wait-ms=500
typeahead-on-select="productSupplierSelected($item, line)"
typeahead-template-url="productSupplierRefList.html" />
where the formatter is:
$scope.formatProduct=function(model) {
return model ? model.code : '';
}
the product code now appears as expected:
Don't use function in typehead. Also be careful about the model properties camel case.
<input ng-model="line.product"
class=" form-control"
ng-keyup="getProductSupplierRefList($event)"
typeahead="ps.Product as ps.Product.Code for ps in productOptions"
typeahead-loading="isLoading"
typeahead-on-select="productSupplierSelected($item, line)"
typeahead-template-url="productSupplierRefList.html"/>
$scope.productOptions = [];
$scope.getProductSupplierRefList = function(evt){
var value = angular.element(evt.target).val();
$http.get('url/' + value).then(funtion(response){
$scope.productOptions = response.data;
})
}
//test ps.Product.Code with _tojson(ps.Product.Code)
$scope._tojson= function(obj){
return angular.toJson(obj);
}

How to insert an image into sql server database?

As said, i'm trying to insert an image in a table, where the type of the field is Varbinary.
What i've done so far :
I've a form with many fields:
#using (Html.BeginForm("InsertProduct", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>PRODUCT</legend>
<div class="editor-label">
#Html.LabelFor(model => model.PRODUCT_ID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PRODUCT_ID)
#Html.ValidationMessageFor(model => model.PRODUCT_ID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PRODUCT_NAME)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.PRODUCT_NAME)
#Html.ValidationMessageFor(model => model.PRODUCT_NAME)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.PRODUCT_IMAGE)
</div>
<div class="editor-field">
<input type="file" name="PRODUCT_IMAGE" id="PRODUCT_IMAGE" style="width: 100%;" />
</div>
<p>
<input type="submit" value="Create" class="btn btn-primary"/>
</p>
</fieldset>
}
And all these fields allow me to construct a PRODUCT object in my controller :
public ActionResult InsertProduct(PRODUCT ord)
{
MigrationEntities1 sent = new MigrationEntities1();
sent.PRODUCT.Add(ord);
sent.SaveChanges();
List<PRODUCT> Products = sent.PRODUCT.ToList();
return View("Products", Products);
}
But when i'm trying to upload the image (by clicking on Create button), i've the following :
entry is not a valid base64 string because it contains a character
that is not base 64
So first of all : is it the right way to deal with images and second, I think I need to do a pre-treatemant on my image to insert it : how to o that ?
Thanks !
Edit :
Thanks to answers received, seems to be good for insertion. But for displaying, I still have issues (only the "not found image" piture is displayed). I've try to do it two ways :
1.
<img src="LoadImage?id=#Model.product.PRODUCT_ID"/>
and in the controller
public Image LoadImage(int id)
{
String serviceAddress = ConfigurationManager.AppSettings["WCFADDRESS"];
DataServiceContext context = new DataServiceContext(new Uri(serviceAddress));
PRODUCT product = context.Execute<PRODUCT>(new Uri(serviceAddress + "prod_id?prod_id=" + id)).ToList().FirstOrDefault();
MemoryStream ms = new MemoryStream(product.PRODUCT_IMAGE);
Image img = Image.FromStream(ms);
return img;
}
And 2. :
#{
if (Model.product.PRODUCT_IMAGE != null)
{
WebImage wi = new WebImage(Model.product.PRODUCT_IMAGE);
wi.Resize(700, 700,true, true);
wi.Write();
}
}
But none of them are working. What am I doing wrong ?
1) Change your database table to have these columns:
1: ProductImage - varbinary(MAX)
2: ImageMimeType - varchar(50)
2) Change your action method like this:
public ActionResult InsertProduct(PRODUCT ord,
HttpPostedFileBase PRODUCT_IMAGE)
{
if (ModelState.IsValid)
{
MigrationEntities1 sent = new MigrationEntities1();
if (image != null)
{
ord.ProductImage= new byte[PRODUCT_IMAGE.ContentLength];
ord.ImageMimeType = PRODUCT_IMAGE.ContentType;
PRODUCT_IMAGE.InputStream.Read(ord.ProductImage, 0,
PRODUCT_IMAGE.ContentLength);
}
else
{
// Set the default image:
Image img = Image.FromFile(
Server.MapPath(Url.Content("~/Images/Icons/nopic.png")));
MemoryStream ms = new MemoryStream();
img.Save(ms, ImageFormat.Png); // change to other format
ms.Seek(0, SeekOrigin.Begin);
ord.ProductImage= new byte[ms.Length];
ord.ImageMimeType= "image/png";
ms.Read(ord.Pic, 0, (int)ms.Length);
}
try
{
sent.PRODUCT.Add(ord);
sent.SaveChanges();
ViewBag.HasError = "0";
ViewBag.DialogTitle = "Insert successful";
ViewBag.DialogText = "...";
}
catch
{
ViewBag.HasError = "1";
ViewBag.DialogTitle = "Server Error!";
ViewBag.DialogText = "...";
}
List<PRODUCT> Products = sent.PRODUCT.ToList();
return View("Products", Products);
}
return View(ord);
}
This action method is just for create. you need some works for edit and index too. If you have problem to doing them, tell me to add codes of them to the answer.
Update: How to show images:
One way to show stored images is as the following:
1) Add this action method to your controller:
[AllowAnonymous]
public FileContentResult GetProductPic(int id)
{
PRODUCT p = db.PRODUCTS.FirstOrDefault(n => n.ID == id);
if (p != null)
{
return File(p.ProductImage, p.ImageMimeType);
}
else
{
return null;
}
}
2) Add a <img> tag in the #foreach(...) structure of your view (or wherever you want) like this:
<img width="100" height="100" src="#Url.Action("GetProductPic", "Products", routeValues: new { id = item.ID })" />
Change the Image type on the sql sever to Byte[] and use something like this. This is how I have stored images in the past.
http://www.codeproject.com/Articles/15460/C-Image-to-Byte-Array-and-Byte-Array-to-Image-Conv
If not, you can always just store the image locally and pass the image location through a string into the SQL data base, this method works well and is quick to set up.
So, here are the modifications to do :
To insert data in the database :
[HttpPost]
public ActionResult InsertProduct(PRODUCT ord, HttpPostedFileBase image)
{
MigrationEntities1 sent = new MigrationEntities1();
if (image != null)
{
ord.PRODUCT_IMAGE = new byte[image.ContentLength];
image.InputStream.Read(ord.PRODUCT_IMAGE, 0, image.ContentLength);
}
sent.PRODUCT.Add(ord);
sent.SaveChanges();
List Products = sent.PRODUCT.ToList();
return View("Products", Products);
}
Note: this is the "light" way, for something that is more complete, have a look to Amin answer.
For displaying :
In the view
<img src="LoadImage?id=#Model.product.PRODUCT_ID"/>
And in the controller :
public FileContentResult LoadImage(int id)
{
String serviceAddress = ConfigurationManager.AppSettings["WCFADDRESS"];
DataServiceContext context = new DataServiceContext(new Uri(serviceAddress));
PRODUCT product = context.Execute<PRODUCT>(new Uri(serviceAddress + "prod_id?prod_id=" + id)).ToList().FirstOrDefault();
return new FileContentResult(product.PRODUCT_IMAGE, "image/jpeg");
}
And everything is ok now, thanks !

The simplest example of Knockback js working with a RESTful webservice such as ServiceStack?

I am looking for a VERY simple example that shows wiring up Knockback code to a backbone model that connects via RESTful service. I am using ServiceStack|c# backend. All of the links below are too complicated and use localStore rather than a RESTful service via url. I also prefer to see examples in Javascript not CoffeeScript.
My example url is something like localhost/entities where hitting this will cause the RESTful webservice to return all of the entities. Hitting it with localhost/entity/1 would return the entity with an Id of 1.
_http://kmalakoff.github.com/knockback/index.html
_https://github.com/kmalakoff/knockback-reference-app/
_https://github.com/addyosmani/todomvc
The following is the example from knockback tutorial on the first link:
Models, Collection, ViewModel, and Bindings:
// Generated by CoffeeScript 1.3.3
var model, view_model;
model = new Backbone.Model({
first_name: "Planet",
last_name: "Earth"
});
view_model = kb.viewModel(model);
view_model.full_name = ko.computed((function() {
return "" + (this.first_name()) + " " + (this.last_name());
}), view_model);
ko.applyBindings(view_model, $('#kb_view_model_computed')[0]);
But there is no mention of how you would wire the backbone model up to your RESTful webservice.
There are examples of how do this via Backbone but I am uncertain as to how things change when using Knockback.
The following links were found, but not helpful:
_http://stackoverflow.com/questions/7992431/using-knockoutjs-backbone-together
_http://stackoverflow.com/questions/9704220/is-knockback-js-production-ready
_http://stackoverflow.com/questions/10434203/defining-models-on-server-side-when-using-mvvm-with-knockout-js
Thanks in advance for any assistance provided. Btw you don't want hyperlinks you get underscores... ;)
With much help and support from Kevin Malakoff from the great Knockback project I was able to get a small example working! I used the ServiceStack Backbone Todos project as a starting point.
c# file: Global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using ServiceStack.Redis;
using ServiceStack.ServiceInterface;
using ServiceStack.WebHost.Endpoints;
namespace MyApp
{
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class PersonService : RestServiceBase<Person>
{
public static Person kevin = new Person { Id = 1, FirstName = "Kevin", LastName = "Malakoff" };
public static Person scott = new Person { Id = 2, FirstName = "Scott", LastName = "Idler" };
public static List<Person> people = new List<Person> { kevin, scott };
public override object OnGet(Person person)
{
if (person.Id != default(int))
return people[person.Id-1];
return people;
}
public override object OnPost(Person person)
{
return base.OnPost(person);
}
public override object OnPut(Person person)
{
return OnPost(person);
}
public override object OnDelete(Person person)
{
return base.OnDelete(person);
}
}
public class AppHost : AppHostBase
{
public AppHost() : base("MyApp", typeof(PersonService).Assembly) { }
public override void Configure(Funq.Container container)
{
ServiceStack.Text.JsConfig.EmitCamelCaseNames = true;
Routes
.Add<Person>("/persons")
.Add<Person>("/persons/{Id}");
}
}
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
new AppHost().Init();
}
}
}
html file: default.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>MyApp2</title>
<script>window.JSON || document.write('<script src="http://ajax.cdnjs.com/ajax/libs/json2/20110223/json2.js">\x3C/script>')</script>
<script src="Scripts/jquery-1.8.0.js" type="text/javascript" ></script>
<script src="Scripts/knockback-full-stack-0.16.1.js" type="text/javascript" ></script>
<script src="myapp.js" type="text/javascript" ></script>
</head>
<body>
<div id="myapp">
<div class="title">
<h1>MyApp</h1>
</div>
<div class="content">
<div id='kb_observable'>
<p>First name: <input class='text' data-bind="value: firstName" /></p>
<p>Last name: <input class='input-small pull-right' data-bind="value: lastName" /></p>
<p>Hello, <span data-bind="text: fullName"></span>!</p>
</div>
<div id="kb_collection_observable">
<div data-bind="if: persons">
<span>Has Persons</span>
</div>
<div data-bind="foreach: persons">
<p>First name: <input class='text' data-bind="value: firstName" /></p>
<p>Last name: <input class='input-small pull-right' data-bind="value: lastName" /></p>
</div>
</div>
</div>
</div>
</body>
</html>
javascript file: myapp.js
$(function() {
//model
var PersonModel = Backbone.Model.extend({ urlRoot: '/MyApp/persons' });
var model = new PersonModel({ id: 1 });
model.fetch();
//viewmodel
var PersonViewModel = function (person) {
this.firstName = kb.observable(person, 'firstName');
this.lastName = kb.observable(person, 'lastName');
this.fullName = ko.computed((function () {
return "" + (this.firstName()) + " " + (this.lastName());
}), this);
};
var personViewModel = new PersonViewModel(model);
//binding
ko.applyBindings(personViewModel, $('#kb_observable')[0]);
//model
var PersonsModel = Backbone.Collection.extend({ model: PersonModel, url: '/MyApp/persons' });
var personsModel = new PersonsModel();
personsModel.fetch();
//viewmodel
var PersonsViewModel = function (persons) {
this.persons = kb.collectionObservable(persons)
};
var personsViewModel = new PersonsViewModel(personsModel);
//binding
ko.applyBindings(personsViewModel, $('#kb_collection_observable')[0]); });
I put together a very simple example. It assumes you already know how to use backbone and knockout so this just gives a quick example of how they can be used together
http://coder2.blogspot.com/2013/02/backbonejs-and-knockoutjs.html

Resources