2015-04-20 33 views
3

之間如何相互參照的對象我有2種型號:Knockout.js - 兩個數組

var ProductViewModel = function() { 
    var self = this; 
    self.ProductList = ko.observableArray([]); 
    self.ProductTypeList = ko.observableArray([]); 

    //...init 2 array and some misc methods 
} 

var ProductModel = function(productid, productname, producttypeid, productprice) { 
    var self = this; 
    self.ProductId = productid; 
    self.ProductName = productname; 
    self.ProductTypeId = producttypeid; 
    self.ProductPrice = productprice; 
} 

var ProductTypeModel= function(producttypeid, producttypename) { 
    var self = this; 
    self.ProductTypeId = producttypeid; 
    self.ProductTypeName = producttypename; 
} 

我在一個視圖模型中使用它們在html文件中:

... 
<table> 
    <thead> 
    <tr> 
    <th>Id</th> 
    <th>Type</th> 
    <th>Name</th> 
    <th>Price</th> 
    </tr> 
    </thead> 
    <tbody data-bind="template: { name: 'row', foreach: ProductList }"> 
    </tbody> 
</table> 
... 
<script id="row" type="html/template"> 
    <tr> 
    <td data-bind="html: ProductId"></td> 
    <td data-bind="html: ProductName"></td> 
    <td data-bind="html: ProductTypeId"></td> <!-- I stuck here!!! --> 
    <td data-bind="html: ProductPrice"></td> 
    </tr> 
</script> 
... 

我希望我的表顯示ProductTypeName而不是ProductTypeId,但我無法將ProductTypeId傳遞到任何函數中以獲取ProductTypeName。

+1

你的問題是不明確的有3類,並沒有:)你shuld定義類型和其他類型的使用他們的任何模型或控制器在完成這些步驟之後,您可以使用foreach作爲類型實例 – dewelloper

+0

@HamitYıldırım,在您的html中調用它們,我認爲它很清楚。我可以綁定我的viewmodel並正確使用它。 'ProductViewModel'可能有點類似於你所說的控制器。 –

回答

3
var ProductViewModel = function() { 
    var self = this; 
    self.ProductList = ko.observableArray([]); 
    self.ProductTypeList = ko.observableArray([]); 

    //...init 2 array and some misc methods 

    self.getProductTypeName = function (productTypeId) { 
    var typeId = ko.unwrap(productTypeId), 
     found = ko.utils.arrayFirst(self.ProductTypeList(), function (productType) { 
      return ko.unwrap(productType.ProductTypeId) === typeId; 
     }); 

    return found ? ko.unwrap(found.ProductTypeName) : null; 
    }; 
}; 

<script id="row" type="html/template"> 
    <tr> 
    <td data-bind="html: ProductId"></td> 
    <td data-bind="html: ProductName"></td> 
    <td data-bind="html: $root.getProductTypeName(ProductTypeId)"></td> 
    <td data-bind="html: ProductPrice"></td> 
    </tr> 
</script> 
+0

困擾我的唯一的事情是,這個函數將被調用到ProductList中的每個項目,並且會多次遍歷ProductTypeList。 我更傾向於將ProductTypeList映射成類似於「{type:Id:typeName, typeId:typeName ... }'以便更快地訪問。爲此,我會在我的主模型上使用一個計算。 getProductTypeName將使用新的計算。 – Olga

+0

是的,但只有在*之後,這就是頁面的性能瓶頸。其他一切都是過早的優化。 – Tomalak

+0

你就在這裏。只是我的習慣,因爲我們的項目後端總是發送相當多的數據。哪一個都在前端處理。 – Olga

1

您有相互關聯的兩個獨立的集合。您可以創建一個模型,通過計算組合對象的可觀測值來管理該關聯。

function ProductListModel (products, productTypes) { 
    this.Products = ko.observableArray(
     ko.utils.arrayMap(products, function (product) { 
      return new ProductModel(
       product.productId, 
       product.productName, 
       product.productTypeId, 
       product.productPrice); 
     }) 
    ); 
    this.ProductTypes = ko.observableArray(
     ko.utils.arrayMap(productTypes, function (productType) { 
      return new ProductTypeModel(
       productType.productTypeId, 
       productType.productTypeName); 
     }) 
    ); 

    this.AssociatedProducts = ko.dependentObservable(function() { 
     var products = this.Products(), 
      productTypes = this.ProductTypes(); 
     return ko.utils.arrayMap(products, function (product) { 
      var productType = ko.utils.arrayFirst(productTypes, function (productType) { 
       return product.ProductTypeId === productType.ProductTypeId; 
      }); 
      return { 
       ProductId: product.ProductId, 
       ProductName: product.ProductName, 
       ProductType: productType.ProductTypeName, 
       ProductPrice: product.ProductPrice, 
      }; 
     }); 
    }, this); 
} 
function ViewModel(data) { 
    var p = new ProductListModel(data.products, data.productTypes); 
    this.Products = p.Products; 
    this.ProductTypes = p.ProductTypes; 
    this.AssociatedProducts = p.AssociatedProducts; 
} 
<tbody data-bind="template: { name: 'row', foreach: AssociatedProducts }"> 
</tbody> 
... 
<script id="row" type="html/template"> 
    <tr> 
     <td data-bind="html: ProductId"></td> 
     <td data-bind="html: ProductName"></td> 
     <td data-bind="html: ProductType"></td> 
     <td data-bind="html: ProductPrice"></td> 
    </tr> 
</script> 

Fiddle

+0

您的解決方案很好!現在,您可以使用'ko.computed'而不是'ko.dependentObservable' [ref](http://knockoutjs.com/documentation/dependentObservables.html)。但是我注意到當你的應用使用ajax來加載數據時它是不安全的。在這種情況下,您必須首先加載'ProductTypes',然後加載'Products'。 –

+0

我知道計算和dependentObservable之間的別名,我只是喜歡後者。一般來說,首先加載哪些值並不重要。雖然這個特定的實現將取決於它們加載的順序,但可以很容易地修復。 –