1

I have an entity from Breeze that might have 20 or so properties, but then I want to wrap the entity in a viewmodel and expose only those few properties as ko.observable(). How do I manage all to do the property change notification?

In c#, I would do something like this:

public double OtherSalesPercent
{
 get { return Model.OtherSalesPercent; }
 set 
 { 
  if (Model.OtherSalesPercent != value)
  {
   Model.OtherSalesPercent = value;
   OnPropertyChanged("OtherSalesPercent");
  }
 }
}

UPDATE Jay thanks for the response. I understand that beeze does this. However, I don't want my view binding directly to the entities, but rather a viewmodel. So think of a view called Apples. And apples is showing a list of apple viewmodels. And each apple entity has 30 different properties, but I want to only expose 3 of those 30 properties on the apple viewmodel. So, I want to create 3 ko.observable properties on the apple viewmodel that will surface those 3 properties on the apple entity. What I have so far is "working", but I don't think its the cleanest. Here is the name property:

var appleViewModel = function(appleEntity) {
   var backingEntity = appleEntity;

   var name = ko.observable(locationEntity.name());
   name.subscribe(function(newValue) {
       backingEntity.name(newValue);
   });

   var vm = {
    name: name
   };

   return vm
};

The other big reason, is I'm using jqxGrid, and they have issues binding to Breeze entities. So really what I'm wanting is a appleViewModel that will surface those properties, but however, if I change the actual apple entity (as in cancelChanges), I want the UI to get that change from the entity).

UPDATE 2

This seems to be giving me everything I want and binds to jqxGrid

var createViewModel = function(appleEntity) {
    var entity = appleEntity;

    var name = ko.observable(entity.name());
        name.subscribe(function(newValue) {
            entity.name(newValue);
        });
        entity.name.subscribe(function(newValue) {
            name(entity.name());
        });

        var vm = {
            name: name
        };

        return vm;
};  

But this just seems so wrong to me. I'm basically wanting two-way binding. So when I change the viewmodel name property it changes the backing entity name... and if I change the backing entity name, it will update the viewmodels name property.

Thanks!

Josh H
  • 13
  • 3

2 Answers2

0

I think this is what you are looking for ko.computed:

var data = {
    OtherSalesPercent: 0.99
};


function Model(data) {
    this.OtherSalesPercentValue = ko.observable(data.OtherSalesPercent);

    this.OtherSalesPercent = ko.computed({
        read: function () { 
            return Model.OtherSalesPercentValue(); 
        },
        write: function (value) {
            if (this.OtherSalesPercentValue() != value) {
                this.OtherSalesPercentValue(value);
            }
        },
        owner: this
    });
}

Example

Joe
  • 80,724
  • 18
  • 127
  • 145
0

Providing i've understood your question, you have a couple of options.

First, by default, breeze makes every entity property 'observable' according to the conventions of the 'modelLibrary' you have selected. So, just to be clear, if you retrieve data that breeze recognizes as an entity, and breeze's model library is 'ko' (the default if you didn't configure one) then every entity property will be a knockout observable automatically.

This only occurs if your query returns 'entities'. Breeze determines if your query result contains entities by looking for a corresponding entityType defined in the client MetadataStore.

If the data returned is not an entity or a collection of entities then breeze simply returns it raw. This can happen if you perform a projection of just selected fields. i.e.

var query = EntityQuery.from("Orders").select("customer, orderDate");

In this case, each item in the query results returned in the promise callback will simply be an object with two simple properties, a 'customer' and an 'orderDate', neither of which will be observable.

Based on your question though, I am wondering if what you want to do is only expose a subset of each server side entity to the client, but still want change management and observability. If this is the case, you can have your server side methods return DTO's and then tell the breeze client that these are 'entityTypes' by specifying the metadata about each DTO's shape. This can be done most easily on the client, by using the MetadataStore.addEntityType method for each DTO shape you plan to return. The breeze documentation goes into more detail on this topic.

I'm not sure if this is what you were asking but... I hope it helps.

Jay Traband
  • 17,053
  • 1
  • 23
  • 44