2012-02-08 74 views
10

Đi qua tài liệu Ember.js, tôi không thể tìm ra cách tạo các mô hình lồng nhau. Giả sử rằng tôi có JSON sau:Làm thế nào để tạo các mô hình lồng nhau trong Ember.js?

App.jsonObject = { 
    id: 1812, 
    name: 'Brokerage Account', 
    positions: [ 
     { 
      symbol: 'AAPL', 
      quantity: '300' 
     }, 
     { 
      symbol: 'GOOG', 
      quantity: '500' 
     } 
    ] 
} 

Nếu tôi tạo ra một đối tượng mô hình như thế này

App.account = Ember.Object.create(App.jsonObject); 

chỉ các thuộc cấp cao nhất (id và tên) được liên kết với các mẫu, các mảng vị trí lồng nhau không không bị ràng buộc một cách chính xác. Kết quả là việc thêm, xóa hoặc cập nhật vị trí không ảnh hưởng đến màn hình. Có một cách thủ công hoặc tự động để chuyển đổi mảng vị trí để nó được ràng buộc nhận thức (tương tự như một ObservableCollection trong WPF)?

Tôi đã tạo một jsfiddle để thử nghiệm với điều này: http://jsfiddle.net/nareshbhatia/357sg/. Như bạn có thể thấy, những thay đổi đối với các thuộc tính mức cao nhất được phản ánh trong đầu ra, nhưng bất kỳ thay đổi nào đối với các vị trí đều không. Tôi sẽ đánh giá rất cao bất kỳ gợi ý về cách làm điều này.

Cảm ơn.

Naresh

Edit: Tình hình lý tưởng sẽ là nếu Ember.js bằng cách nào đó có thể phân tích thức ăn JSON của tôi vào đối tượng Ember.js lồng nhau. Ví dụ, nếu tôi định nghĩa một cách rõ ràng các lớp của tôi như sau, có thể hỗ trợ Ember.js để tạo ra các đối tượng thích hợp không?

App.Account = Ember.Object.extend({ 
    id: null, 
    name: null, 
    positions: Ember.ArrayProxy.create() 
}); 

App.Position = Ember.Object.extend({ 
    symbol: null, 
    quantity: null, 
    lastTrade: null 
}); 

App.account = App.Account.create(App.jsonObject); 

Mục tiêu cuối cùng của tôi là hiển thị cấu trúc này trong lưới phân cấp có thể mở rộng/thu gọn ở cấp tài khoản. Đến từ thế giới WPF/Silverlight, nó là khá dễ dàng để làm một cái gì đó như thế này. Tất cả những gì bạn cần làm là chỉ định một mẫu lồng nhau cho lưới trong XAML và nó biết cách diễn giải mô hình của bạn. Bạn có thể tìm thấy một ví dụ here - nó không phải là quá khó khăn để làm theo. Tôi tự hỏi nếu một cái gì đó như thế này là có thể trong Ember.js.

+0

Tôi không quen thuộc với WPF hoặc điều khiển của nó (không hoạt động w/it trong gần 4 năm), nhưng có vẻ như một thứ như thế không quá tệ để thực hiện trong Ember & Handlebars. –

Trả lời

5

Bạn cần sử dụng pushObject không push khi thêm vào đối tượng mảng Ember với các ràng buộc. Và có lẽ bạn nên sử dụng get() khi truy cập vào thuộc tính positions. Xem jsFiddle của tôi để sửa chữa.

http://jsfiddle.net/ud3323/Y5nG5/

+0

Cảm ơn. Điều này rất hữu ích vì nó cho phép tôi đối xử với các vị trí như là một tài sản hạng nhất. Tuy nhiên, nó vẫn không giải quyết được vấn đề với các thuộc tính ở cấp lồng nhau (dòng nhận xét gần cuối của fiddle của tôi). Tôi đã chỉnh sửa câu hỏi của mình để làm rõ mục tiêu cấp cao hơn của tôi. Tôi sẽ thực sự quan tâm đến việc của bạn về điều đó. Cảm ơn một lần nữa. – Naresh

+0

Đối với một mảng lồng nhau, bạn sẽ phải lặp qua mảng và tạo các đối tượng Ember trong mỗi mảng. Tôi không nghĩ rằng có bất cứ điều gì được xây dựng vào Ember mà làm điều này cho bạn. –

+0

là fiddle này đi? – Qrilka

1

tôi đã tạo ra một nhà máy đối tượng đệ quy mà bạn có thể thích:

Nó sẽ lặp qua các đối tượng và tạo Ember Mảng hoặc đối tượng lồng nhau, trả lại một Ember cây Object đầy đủ!

Đây là nguồn để bạn tham khảo, và một fiddle JS: http://jsfiddle.net/SEGwy/2/

Xin lưu ý: fiddle viết đầu ra để giao diện điều khiển, do đó bạn sẽ không thấy bất kỳ kết quả trên màn hình.

RecursiveObject = { 

     // http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/ 
     TypeOf: function (input) { 
      try { 
       return Object.prototype.toString.call(input).match(/^\[object\s(.*)\]$/)[1].toLowerCase(); 
      } catch (e) { 
       return typeof input; 
      } 
     }, 

     // Factory method.. 
     create: function (args) { 

      args = args || {}; 
      ctxt = this; 

      switch (this.TypeOf(args)) { 

       // Return an Ember Array 
       case "array": 

        var result = Ember.A(); 

        for (var i = 0; i < args.length; i++) { 
         x = this.create(args[i]); 
         result.push(x); 
        }; 

        break; 

       // Or a recursive object. 
       case "object": 

        var result = Ember.Object.create(); 

        $.each(args, function (key, value) { 

         result.set(key, ctxt.create(value)); 

        }); 

        break; 

       default: 

        // Or just return the args. 
        result = args; 
        break; 

      } 

      return result; 

     } 

    } 

    // Example 

    jsonObject = { 
    id: 1812, 
    name: 'Brokerage Account', 
    positions: [ 
     { 
      symbol: 'AAPL', 
      quantity: '300' 
     }, 
     { 
      symbol: 'GOOG', 
      quantity: '500' 
     } 
    ] 
    } 

    x = RecursiveObject.create(jsonObject); 
    console.log(x); 
0

Tôi đã viết nhà máy sản xuất mô hình đơn giản của riêng mình dựa trên giải pháp của Alexandros K nhưng hỗ trợ các mô-đun ES6.Nghĩ tôi sẽ chia sẻ nó :)

import Ember from 'ember'; 

var ModelFactory = Ember.Object.extend({}); 

ModelFactory.reopenClass({ 
    getType(obj) { 
     if(!obj) { 
      return null; 
     } 

     if(Array === obj.constructor) { 
      return "array"; 
     } 
     else if(typeof obj === "object") { 
      return "object"; 
     } 

     return null; 
    }, 

    // Factory method.. 
    create: function (arg) { 

     const _this = this; 

     switch (this.getType(arg)) { 

      // Return an Ember Array 
      case "array": 

       var newArray = []; 

       arg.forEach(function(item) { 
        newArray.pushObject(_this.create(item)); 
       }); 

       return newArray; 

      // Or a recursive object. 
      case "object": 

       var newObject = Ember.Object.create(); 

       for (var key in arg) { 
        if (arg.hasOwnProperty(key)) { 
         newObject.set(key, this.create(arg[key])); 
        } 
       } 

       return newObject; 

      default: 

       // Or just return the args. 
       return arg; 
     } 
    } 
}); 


export default ModelFactory; 

Cách sử dụng:

ModelFactory.create(json) 
-1

trả lời thích hợp cho Ember 2.5.0/tháng năm 2016

Tôi đã có một câu hỏi tương tự (xem dưới đây để biết trường hợp của tôi) và đã nhận được thất vọng bởi rất nhiều đề ngày/không còn hữu ích để đăng những gì tôi đã học ở đây trong trường hợp nó là hữu ích cho những người khác vấp ngã trên trang này.

TL; DR: Trong các phiên bản gần đây của Ember, bạn xác định mô hình của mình bằng cách mở rộng đối tượng Model trong dữ liệu ember với các thuộc tính bạn muốn. Các thuộc tính được xác định bằng cách gọi DS.attr(type) (trong đó thông số type có thể được bỏ qua để chuyển qua bất kỳ loại nào bạn muốn, ví dụ: các đối tượng lồng nhau từ JSON của bạn).

Vì vậy, cho câu hỏi này bạn có thể tạo app/models/account (có thể bằng cách sử dụng ember-cli ->ember g resource account):

import Model from 'ember-data/model'; 
import attr from 'ember-data/attr'; 
import { hasMany } from 'ember-data/relationships'; 

export default Model.extend({ 
    name: attr('string'), 
    positions: hasMany('position') 
}); 

và tương tự cho app/models/position:

import Model from 'ember-data/model'; 
import attr from 'ember-data/attr'; 

export default Model.extend({ 
    symbol: attr('string'), 
    quantity: attr('number') 
}); 

trường hợp của tôi:

Tôi muốn có một số device được liên kết với số connection có thể là kết nối nối tiếp hoặc TCP, mỗi kết nối có các tùy chọn/tham số khác nhau. Trong JS đơn giản, tôi sẽ đã làm một cái gì đó như thế này:

[{ 
    name: "My serial device", 
    connection: { 
     type: "serial", 
     options: { 
      port: "COM1", 
      baud: 115200, 
      data_bits: 8, 
      parity: "none", 
      stop_bits: 1, 
      flow_control: "none" 
     } 
    } 
}, { 
    name: "My TCP/IP device", 
    connection: { 
     type: "tcp", 
     options: { 
      host: "127.0.0.1", 
      port: 23 
     } 
    } 
}] 

trong Ember này chuyển sang một mô hình device với một tài sản kết nối có loại là một đối tượng (trái không xác định):

import Model from 'ember-data/model'; 
import attr from 'ember-data/attr'; 

export default Model.extend({ 
    name: attr('string'), 
    connection: attr() 
}); 

Nếu bạn đang tự hỏi tiêu chí tốt là gì để xác định liệu một mô hình nào đó có phải là mô hình riêng (với mối quan hệ belongsTo, hasMany, v.v.) hay không, một câu hỏi đơn giản để bắt đầu là liệu tài nguyên được đề cập sẽ có số id hay không Liên kết với nó. Trong trường hợp này, nó không có ý nghĩa nhiều để theo dõi các kết nối và các thiết bị một cách riêng biệt, vì vậy tôi đã chọn không tạo một mô hình riêng biệt cho các kết nối.

Các vấn đề liên quan