web-dev-qa-db-fra.com

Définition d'attributs sur une collection - Backbone JS

Les collections dans le backbone js ne vous permettent pas de set attributs, mais je trouve souvent qu'il est nécessaire de stocker des méta-informations sur une collection. Quel est le meilleur endroit pour définir ces informations?

56
idbentley

Il est probablement préférable d'utiliser Collection exactement comme il était prévu: comme un ensemble de modèles. (Julien a déjà commenté cela sur l'OP, je voudrais expliquer pourquoi je pense qu'il a raison)

Disons que vous pensez à une bibliothèque (collection) de livre (modèle) comme dans les exemples de documentation de Backbone. Il est logique que vous ayez des méta-informations sur la bibliothèque que vous souhaitez stocker, comme l'adresse où se trouve cette bibliothèque de livres.

L'astuce n'est pas de la considérer comme une méta-information. Vous avez une bibliothèque qui a beaucoup de propriétés, et l'une de ces propriétés est sa collection de livres.

var Book = Backbone.Model.extend({ 
    title: "Moby Dick"
});

var Collection = Backbone.Collection.extend({
    model: Book
});

var Library = {
    address: '45th Street',
    collection: Collection
};

Dans cet exemple, j'ai défini la bibliothèque comme un simple objet JavaScript. Évidemment, vous pouvez également faire de Library un modèle, de sorte qu'il ait toutes les cloches et les sifflets de Backbone. Mon point ici est que vous devez représenter la réalité de manière plus réaliste en prenant un peu de recul et en voyant que les propriétés supplémentaires que vous souhaitez affecter à la collection sont en fait les propriétés sœurs d'un objet d'un niveau supérieur: la bibliothèque dans ce cas .


17
Wytze

Juste .extend la collection avec une fonction de stockage de métadonnées.

var MyCollection = Backbone.Collection.extend({
    initialize: function() {
        ...

        this._meta = {};
    },
    model: ...
    meta: function(prop, value) {
        if (value === undefined) {
            return this._meta[prop]
        } else {
            this._meta[prop] = value;
        }
    },
});

var collection = new MyCollection();
collection.add(someModels);
collection.meta("someProperty", value);

...

var value = collection.meta("someProperty");

Il peut y avoir de meilleurs endroits pour stocker des métadonnées spécifiques mais cela dépend complètement de ce que sont les métadonnées.

Pour stocker des métadonnées génériques, étendez votre constructeur de collection avec une méthode pour y faire face qui devrait fonctionner.

Méfiez-vous que si ces métadonnées doivent être stockées et chargées à partir du serveur, vous avez une tâche plus importante à accomplir.

44
Raynos

J'ai amélioré l'approche de Raynos avec le déclenchement d'événements, afin que nous puissions nous lier à la mise à jour des attributs de la collection.

cls.groups = Backbone.Collection.extend({

    // ...

    // Reference to this collection's model.
    model: cls.group,

    initialize: function() {
        this._attributes = {}
    },

    // Extend collection with ability to store attributes and trigger events on attributes changing
    attr: function(prop, value) {
        if (value === undefined) {
            return this._attributes[prop]
        } else {
            this._attributes[prop] = value;
            this.trigger('change:' + prop, value);
        }
    },

    // ...

});


cls.group = Backbone.View.extend({

    // ...

    initialize: function() {

        // Catching attribute update
        app.groups.on('change:selected', function(value) {
            // ...
        }, this);
    },

    // ...

    events: {
        'click' : function(e) {
            // Set collection meta attribute on model's view click event
            app.groups.attr('selected', this.model.cid);
        }
    }

    // ...

});
7
Antipin

L'utilisation de la fonction meta de la solution @Raynos avec un seul paramètre n'a pas fonctionné pour moi. J'ai donc utilisé le code suivant:

var MyCollection = Backbone.Collection.extend({
    initialize: function() {
        this._meta = {};
    },
    put: function(prop, value) {
        this._meta[prop] = value;
    },
    get: function(prop) {
        return this._meta[prop];
    }
});

var collection = new MyCollection();
collection.put("someProperty", 12);
alert(collection.get("someProperty"));

J'espère que ça vous aidera.

4
yves amsellem