Définir id et className dynamicment dans les vues Backbone.js

Je suis en train d’apprendre et d’utiliser Backbone.js.

J’ai un modèle d’article et une vue d’article correspondante. Chaque instance de modèle possède des atsortingbuts item_class et item_id, que je souhaite voir apparaître comme atsortingbuts “id” et “class” de la vue correspondante. Quelle est la bonne façon d’y parvenir?

Exemple:

var ItemModel = Backbone.Model.extend({ }); var item1 = new ItemModel({item_class: "nice", item_id: "id1"}); var item2 = new ItemModel({item_class: "sad", item_id: "id2"}); var ItemView = Backbone.View.extend({ }); 

Comment dois-je implémenter la vue pour que les vues se traduisent par:

 

Dans la plupart des exemples que j’ai vus, l’ el de la vue sert d’élément wrapper sans signification dans lequel il faut écrire manuellement le code «sémantique».

 var ItemView = Backbone.View.extend({ tagName: "div", // I know it's the default... render: function() { $(this.el).html("
Some stuff
"); } });

Donc, quand rendu, on obtient

 
Some stuff

Mais cela semble être un gaspillage – pourquoi avoir le div externe? Je veux que l’ el traduise directement dans la div interne!

Résumé: définir dynamicment les atsortingbuts de vue avec les données de modèle

http://jsfiddle.net/5wd0ma8b/

 // View class with `atsortingbutes` method var View = Backbone.View.extend( { atsortingbutes : function () { // Return model data return { class : this.model.get( 'item_class' ), id : this.model.get( 'item_id' ) }; } // atsortingbutes } ); // Pass model to view constructor var item = new View( { model : new Backbone.Model( { item_class : "nice", item_id : "id1" } ) } ); 
  • Cet exemple suppose que vous permettez à Backbone de générer un élément DOM pour vous.

  • La méthode atsortingbutes est appelée après la définition des propriétés passées au constructeur de la vue (dans ce cas, le model ), ce qui vous permet de définir dynamicment les atsortingbuts avec les données du modèle avant que Backbone ne crée el .

  • Contrairement à certaines des autres réponses: ne code pas dur les valeurs d’atsortingbut dans la classe de vue, les définit dynamicment à partir des données de modèle; n’attend pas que render() définisse des valeurs d’attr; ne pas définir à plusieurs resockets des valeurs d’attr dans chaque appel à render() ; ne définit pas inutilement manuellement les valeurs d’attr sur l’élément DOM.

  • Notez que si vous définissez la classe lors de l’appel de Backbone.View.extend ou d’un constructeur de vues (par exemple, new Backbone.View ), vous devez utiliser le nom de la propriété DOM, className , mais si vous le définissez via l’ atsortingbutes hash / method (comme dans ce cas). Par exemple, vous devez utiliser le nom d’atsortingbut, class .

  • À partir de Backbone 0.9.9:

    Lors de la déclaration d’une vue … el , tagName , id et className peuvent maintenant être définis en tant que fonctions, si vous souhaitez que leurs valeurs soient déterminées lors de l’exécution.

    Je mentionne cela dans le cas où il serait utile de remplacer une méthode d’ atsortingbutes comme illustré.

Utiliser un élément existant

Si vous utilisez un élément existant (par exemple en passant el au constructeur de la vue) …

 var item = new View( { el : some_el } ); 

… alors les atsortingbutes ne seront pas appliqués à l’élément. Si les atsortingbuts souhaités ne sont pas déjà définis sur l’élément ou si vous ne souhaitez pas dupliquer ces données dans votre classe de vue et dans un autre emplacement, vous pouvez append une méthode d’ initialize à votre constructeur de vue qui applique des atsortingbutes à el . Quelque chose comme ça (en utilisant jQuery.attr ):

 View.prototype.initialize = function ( options ) { this.$el.attr( _.result( this, 'atsortingbutes' ) ); }; 

Utilisation de el , rendu, en évitant le wrapper

Dans la plupart des exemples que j’ai vus, l’el de la vue sert d’élément wrapper sans signification dans lequel il faut écrire manuellement le code «sémantique».

Il n’y a pas de raison que view.el être “un élément enveloppant sans signification”. En fait, cela briserait souvent la structure DOM. Si une classe de vue représente un élément

  • par exemple, elle doit être rendue sous la forme d’un

  • – le rendu en tant que

    ou tout autre élément briserait le modèle de contenu. Vous voudrez probablement vous concentrer sur la configuration correcte de l’élément de votre vue (en utilisant des propriétés telles que tagName , className et id ), puis en rendant son contenu par la suite.

    Les options permettant d’interagir avec les objects de vue Backbone avec le DOM sont grandes ouvertes. Il existe 2 scénarios initiaux de base:

    • Vous pouvez attacher un élément DOM existant à une vue Backbone.

    • Vous pouvez autoriser Backbone à créer un nouvel élément déconnecté du document, puis à l’insérer dans le document.

    Vous pouvez générer le contenu de l’élément de différentes manières (définissez une chaîne littérale, comme dans votre exemple, utilisez une bibliothèque de templates comme Moustache, Handlebars, etc.). Comment utiliser la propriété el de la vue dépend de ce que vous faites.

    Élément existant

    Votre exemple de rendu suggère que vous avez un élément existant que vous assignez à la vue, bien que vous n’indiquiez pas l’instanciation des vues. Si tel est le cas, et que l’élément est déjà dans le document, vous pouvez faire quelque chose comme ceci (mettre à jour le contenu de el , mais ne pas modifier le contenu lui-même):

     render : function () { this.$el.html( "Some stuff" ); } 

    http://jsfiddle.net/vQMa2/1/

    Élément généré

    Disons que vous n’avez pas d’élément existant et que vous autorisez Backbone à en générer un pour vous. Vous voudrez peut -être faire quelque chose comme ça (mais il est probablement préférable de concevoir les choses de manière à ce que votre vue ne soit pas responsable de savoir quoi que ce soit en dehors de lui-même):

     render : function () { this.$el.html( "Some stuff" ); $( "#some-container" ).append( this.el ); } 

    http://jsfiddle.net/vQMa2/

    Modèles

    Dans mon cas, j’utilise des modèles, par exemple:

     

    Le modèle représente la vue complète. En d’autres termes, il n’y aura pas de wrapper autour du template – div.player sera l’élément racine ou le plus à l’extérieur de ma vue.

    Ma classe de joueur ressemblera à ceci (avec un exemple très simplifié de render() ):

     Backbone.View.extend( { tagName : 'div', className : 'player', atsortingbutes : function () { return { id : "player-" + this.model.cid }; }, // atsortingbutes render : function { var rendered_template = $( ... ); // Note that since the top level element in my template (and therefore // in `rendered_template`) represents the same element as `this.el`, I'm // extracting the content of `rendered_template`'s top level element and // replacing the content of `this.el` with that. this.$el.empty().append( rendered_template.children() ); } } ); 

    À votre avis, il suffit de faire quelque chose comme ça

     var ItemView = Backbone.View.extend({ tagName: "div", // I know it's the default... render: function() { $(this.el).attr('id', 'id1').addClass('nice').html('Some Stuff'); } }); 

    Vous pouvez définir les propriétés className et id sur l’élément racine: http://documentcloud.github.com/backbone/#View-extend

     var ItemView = Backbone.View.extend({ tagName: "div", // I know it's the default... className : 'nice', id : 'id1', render: function() { $(this.el).html("Some stuff"); } }); 

    EDIT Exemple d’exemple de définition d’ID basé sur les parameters du constructeur

    Si les vues sont construites comme mentionné:

     var item1 = new ItemModel({item_class: "nice", item_id: "id1"}); var item2 = new ItemModel({item_class: "sad", item_id: "id2"}); 

    Ensuite, les valeurs peuvent être définies de cette manière:

     // ... className: function(){ return this.options.item_class; }, id: function(){ return this.options.item_id; } // ... 

    Je sais que c’est une vieille question, mais ajoutée pour référence. Cela semble être plus facile dans les nouvelles versions de backbone. Dans Backbone 1.1, les propriétés id et className sont évaluées dans la fonction ensureElement (voir depuis la source ) en utilisant le trait de soulignement _.result ce _.result signifie que si className ou id est une fonction, elle sera appelée, sinon sa valeur sera utilisée.

    Donc, vous pouvez donner className directement dans le constructeur, donner un autre paramètre qui serait utilisé dans className, etc … Beaucoup d’options

    donc cela devrait fonctionner

     var item1 = new ItemModel({item_class: "nice", item_id: "id1"}); var item2 = new ItemModel({item_class: "sad", item_id: "id2"}); var ItemView = Backbone.View.extend({ id: function() { return this.model.get('item_id'); }, className: function() { return this.model.get('item_class'); } }); 

    Les autres exemples ne montrent pas comment saisir les données du modèle. Pour append dynamicment un identifiant et une classe à partir des données du modèle:

     var ItemView = Backbone.View.extend({ tagName: "div", render: function() { this.id = this.model.get('item_id'); this.class = this.model.get('item_class'); $(this.el).attr('id',this.id).addClass(this.class).html('Some Stuff'); } }); 

    Vous devez supprimer tagName et déclarer un el.

    ‘tagName’ signifie que vous voulez que le backbone crée un élément. Si l’élément existe déjà dans le DOM, vous pouvez spécifier un el comme:

     el: $('#emotions'), 

    et ensuite:

     render: function() { $(this.el).append(this.model.toJSON()); } 

    Essayez d’affecter les valeurs dans la méthode initialize, cela affectera directement l’ID et la classe à l’atsortingbut div de manière dynamic.

     var ItemView = Backbone.View.extend( { tagName : "div", id : '', class : '', initialize : function( options ) { if ( ! _.isUndefined( options ) ) { this.id = options.item_id; this.class= options.item_class; } }, render : function() { $( this.el ).html( this.template( "stuff goes here" ) ); } } ); 

    Voici un moyen minimal de modifier dynamicment la classe de l’élément de la vue via un modèle et de le mettre à jour sur les modifications du modèle.

     var VMenuTabItem = Backbone.View.extend({ tagName: 'li', events: { 'click': 'onClick' }, initialize: function(options) { // auto render on change of the class. // Useful if parent view changes this model (eg via a collection) this.listenTo(this.model, 'change:active', this.render); }, render: function() { // toggle a class only if the atsortingbute is set. this.$el.toggleClass('active', Boolean(this.model.get('active'))); this.$el.toggleClass('empty', Boolean(this.model.get('empty'))); return this; }, onClicked: function(e) { if (!this.model.get('empty')) { // optional: notify our parents of the click this.model.sortinggger('tab:click', this.model); // then update the model, which sortingggers a render. this.model.set({ active: true }); } } });