2012-01-27 14 views
8

यह कुछ हद तक उदाहरण है, लेकिन मुझे विश्वास है कि यह बिंदु पूरी हो जाता है।Backbone.js - एक संग्रह कैसे बनाएं जिसमें बाध्यकारी गुण हों

आइए कहें कि मेरे पास रीढ़ की हड्डी कार संग्रह है। और संग्रह के लिए मैं एक संपत्ति चाहता हूं जिसे वैध है। मैं चाहता हूं कि अन्य ऑब्जेक्ट्स बाध्य करने में सक्षम हों और वैध है जब वैध परिवर्तन होता है। संग्रह पूरी तरह से संग्रह में मॉडलों के आधार पर बदल दिया जाएगा।

उदाहरण के लिए, यदि सभी कार हर कार पर बंद हैं, तो isValid को सच में बदलना चाहिए। जब वैलिड बदलता है, तो सभी कार्यों को बाध्य किया जाता है, वैध परिवर्तन घटना को निकाल दिया जाना चाहिए।

मेरा सवाल यह है कि, मैं एक संग्रह कैसे बना सकता हूं जिसमें बाध्यकारी गुण हैं जो मॉडल गुणों के समान काम करता है?

यह वह कोड है जिसे मैं काम करना चाहता हूं।

var Car = Backbone.Model.extend({}); 
var Cars = Backbone.Collection.extend({ 
    model: Car, 
    url: "Cars", 
    isValid: false, //Here's the property that I want bindable 
        //but do not know how to accomplish this. 
}); 

var cars = new Cars(); 

//Call a function when cars.isValid changes 
cars.bind("change:isValid", carsIsValidChanged, cars) 

//Not sure if this what the function would look like 
//but would need access to cars.isValid or just the car collection 
function carsIsValidChanged(isValid){ 
    console.log(isValid); 
} 


अद्यतन

नीचे एक जवाब के रूप में मेरे पूर्ण समाधान देखें।

उत्तर

5

इसलिए संग्रह पर संपत्ति परिवर्तनों का जवाब देने के लिए कोई 'अंतर्निर्मित' तरीका नहीं है, क्योंकि वास्तव में एक संग्रहित गुण नहीं है (जिसे मैं जानता हूं) संग्रह पर गुण रखने के लिए। हालांकि, यह अभी भी पूरी तरह से संभव है, मुझे लगता है। (अपरीक्षित है, लेकिन काफी करीब होना चाहिए)

var Car = Backbone.Model.extend({}); 
var Cars = Backbone.Collection.extend({ 
    model: Car, 
    url: "Cars", 
    initialize: function() { 
     var self = this; 
     this.isValid = false; 
     this.bind('add', function() { 
      var curValid = true; 
      self.each(function(car) { 
      if(car.get('is_locked') != true) { 
       curValid = false; 
      } 
      }); 
      if(curValid != self.isValid) { 
      self.isValid = curValid; 
      self.trigger('change:isValid', self.isValid, self); 
      } 
     }); 
    }     
}); 

// instantiate a new Cars collection 
var cars = new Cars(); 


function carsIsValidChanged(isValid){ 
    console.log(isValid); 
} 

//Call a function when cars.isValid changes 
cars.bind("change:isValid", carsIsValidChanged) 

एक ध्यान दें: आप अगर है नहीं करना चाहती: आप की तरह मॉडल हैं या संपत्ति यूआरएल के रूप में सूचीबद्ध। ऐसा लगता है कि रीढ़ की हड्डी अजीब हो सकती है, और आपका अस्तित्व संग्रह के सभी उदाहरणों को फैला सकता है। उन्हें प्रारंभिक के रूप में परिभाषित करना बेहतर होता है, फिर हर बार जब आप उस संग्रह को तुरंत चालू करते हैं, तो आपके पास इस विधि के द्वारा सुलभ है। वैध। jsFiddle Complete example

@spotmat मुझे सही दिशा में डाल दिया है, लेकिन मैं अतिरिक्त कार्यक्षमता जोड़ने के लिए की जरूरत:

+0

उत्तर के लिए धन्यवाद। मेरा मानना ​​है कि आपने मुझे सही दिशा में इंगित किया है। प्रारंभिक में सत्यापित की जाने वाली जानकारी की सराहना करें। जब मैं अपने कामकाजी समाधान के साथ खत्म करूँगा, तो मैं इसे पोस्ट करूंगा। –

2

यहाँ इस सवाल का मेरा पूरा समाधान है।

  • संग्रह contructor इसे करने के लिए पारित डेटा
  • जब एक मॉडल IsLocked संपत्ति संग्रह अद्यतन किया जाता है फिर से मान्य करने की

मैं की जरूरत है संभाल करने की जरूरत है: यहाँ कुछ आइटम को हल किया जा करने के लिए आवश्यक है कि मुझे यकीन नहीं है कि संग्रह में बाध्यकारी गुण जोड़ना एक अच्छा विचार है, लेकिन यह पता लगाने में कुछ मजेदार था, और मैंने बहुत कुछ सीखा।

var log = {};//this is for debugging 
_.extend(log, Backbone.Events); 

var Car = Backbone.Model.extend({}); 

var Cars = Backbone.Collection.extend({ 
    model: Car, 
    url: "scripts/data/Cars.json", 
initialize: function() { 
    var _this = this; 

    this.isValid = false; //user should bind to "change:isValid" 
    this._isPending = false; //This is so that 

    this.bind("add", this.modelAdded, this); 
    this.bind("reset", this.modelsAdded, this); 

    if (this.length > 0) { 
     //Model passed in though the constructor will not be binded 
     //so call modelsAdded 
     this.modelsAdded(this); 
    } 
}, 

modelsAdded: function (collection) { 
    this._isPending = true 
    log.trigger("log", ["modelsAdded: " + collection.length]); 
    collection.each(this.modelAdded, this); //Do nut remove "this" param. It need when modelAdded gets called 
    this._isPending = false 
    this._validate(); 
}, 

modelAdded: function (model) { 
    log.trigger("log", ["modelAdded: " + model.get("Model") + "; IsLocked: " + model.get("IsLocked")]); 
    //!!!for each model added to the colleciton bind 
    //its IsLocked property to the collection modelIsLockedChange function 
    model.bind("change:IsLocked", this.modelIsLockedChanged, this); 
    if (this._isPending == false) { 
     this._validate(); 
    } 
}, 

modelIsLockedChanged: function (model) { 
    log.trigger("log", ["modelIsLockedChanged:" + model.get("Model") + "; IsLocked: " + model.get("IsLocked")]); 
    this._validate(); 
}, 

_validate: function() { 
    var isValid = true; 
    this.each(function (model) { 
     if (model.get("IsLocked") == false) { 
      isValid = false 
     } 
    }); 

    if (this.isValid != isValid) { 
     this.isValid = isValid 
     cars.trigger("change:isValid", [this.isValid]) 
    } 
    }, 
}); 

यह दृश्य डिबगिंग उद्देश्यों के लिए है

var Logger = Backbone.View.extend({ 
    el: $("#output"), 

    initialize: function(){ 
     log.bind("log", this.logMessage, this) 
    }, 

    render: function(){ 
     return $(this.el).html(""); 
    }, 

    logMessage: function(message){ 
     $(this.el).find("ul").append("<li>" + message[0] + "</li>"); 
    } 
}) 

निम्नलिखित कोड संग्रह

var logger = new Logger(); 
log.bind("log", function(message){ 
    console.log(message[0]); 
}); 

var carsData = [ 
    { "Model": "Chevy Camero", "Year": 1982, "IsLocked": true }, 
    { "Model": "Ford F-150", "Year": 2011, "IsLocked": false } 
] 

var cars = new Cars(carsData); 
cars.bind("change:isValid", function(isValid){ 
    log.trigger("log", ["change:isValid: " + isValid]); 
}); 

cars.add({ "Model": "Toyota Tacoma", "Year": 2006, "IsLocked": true }); 
cars.at(1).set({ "IsLocked": true }); 
परीक्षण करने के लिए प्रयोग किया जाता है
5

आप कुछ इस तरह इस्तेमाल कर सकते हैं;

Backbone.Collection.prototype.bindableProperty = function (key, val) { 
    var self = this; 
    Object.defineProperty(this, key, { 
     configurable: false, 
     get: function() { return val; }, 
     set: function (v) { 
      val = v; 
      self.trigger('change:'+key, val) 
     } 
    }); 
}; 

बस संपत्ति जोड़ने के लिए ऐसा करें;

var Cars = Backbone.Collection.extend({ 
    model: Car, 
    url: "Cars", 
    initialize: function() { 
    this.bindableProperty('isValid', false); 
    } 
}); 

हालांकि चेतावनी; IE के पुराने संस्करण ऑब्जेक्ट.डेफिनप्रोपर्टी का समर्थन नहीं करते हैं।

+0

मैं इस शाम को आजमाउंगा। –

+1

आपके उत्तर के लिए धन्यवाद स्टीफन बेलेंजर। आपके द्वारा प्रदान किया जाने वाला समाधान शायद सबसे साफ है, लेकिन जैसा कि आपने बताया है कि यह IE8 के साथ काम नहीं करता है। भले ही मुझे आपकी सिफारिश के साथ काम करने के लिए मेरा उदाहरण प्राप्त करने के लिए थोड़ा और कोड लिखना पड़ा, मुझे अब निम्न कोड को मैन्युअल रूप से कॉल करने की आवश्यकता नहीं है, जो बहुत अच्छा है: 'cars.trigger (" change: isValid " , [this.isValid]) ' अब जब भी वैध संपत्ति बदल जाती है, तो ईवेंट स्वचालित रूप से निकाल दिया जाता है। [जेएसएफडल उदाहरण] (http://jsfiddle.net/BarDev/ae63d/) –

+0

बस भविष्य में इसे पढ़ने वाले किसी भी व्यक्ति के लिए; यह आईई 9 + में काम करता है, और आंशिक रूप से आईई 8 में, जैसा कि यहां बताया गया है; https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty#ie8-specific –

संबंधित मुद्दे