85 votes

Définition d’id et className dynamiquement en Backbone.js vues

Je suis dans le processus de l'apprentissage et de l'utilisation Backbone.js.

J'ai un Élément de modèle et d'un Point de vue. Chaque instance du modèle a item_class et item_id attributs, que je veux être reflété dans le " id " et "class" attributs de la vue correspondante. Quelle est la bonne façon d'atteindre cette ?

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 mettre en œuvre la vue, de sorte que le point de vue " el volonté de traduire:

<div id="id1" class="nice"></div>
<div id="id2" class="sad"> </div>

Dans la plupart des exemples que j'ai vu, le point de vue de l' el sert un sens wrapper élément à l'intérieur de laquelle on a à écrire manuellement le 'sémantique' code.

var ItemView = Backbone.View.extend({
   tagName:  "div",   // I know it's the default...

   render: function() {
     $(this.el).html("<div id="id1" class="nice"> Some stuff </div>");
   }       
});

Donc, une fois rendu, on obtient

<div> <!-- el wrapper -->
    <div id="id1" class="nice"> Some stuff </div>
</div>

Mais cela semble être un gaspillage pourquoi les externes div ? Je veux la el de traduire directement dans l'intérieur de la div!

133voto

JMM Points 4032

Résumé: définir de façon dynamique les attributs de vue avec les données du modèle

http://jsfiddle.net/5wd0ma8b/

// View class with `attributes` method
var View = Backbone.View.extend( {
  attributes : function () {
    // Return model data
    return {
      class : this.model.get( 'item_class' ),
      id : this.model.get( 'item_id' )
    };
  }
  // attributes
} );

// Pass model to view constructor
var item = new View( {
  model : new Backbone.Model( {
    item_class : "nice",
    item_id : "id1"
  } )
} );
  • Cet exemple suppose que vous êtes épine Dorsale permettant de générer un élément du DOM pour vous.

  • L' attributes méthode est appelée après que les propriétés passé pour le constructeur de la vue sont définis (dans ce cas, model), vous permettant de définir de manière dynamique les attributs avec le modèle de données avant de la Dorsale crée el.

  • Contrairement à certains des autres réponses: ne pas coder en dur les valeurs d'attribut dans la classe de la vue, de façon dynamique des ensembles de données de modèle; n'attendez pas d' render() pour définir l'attribut de vals; n'a pas d'maintes reprises attr vals-les-bains lors de chaque appel d' render(); ne pas inutilement définir manuellement attr vals-les-bains sur l'élément du DOM.

  • Notez que si la définition de la classe lors de l'appel d' Backbone.View.extend ou d'une vue sur le constructeur (par exemple, new Backbone.View), vous devez utiliser le DOM nom de la propriété, className, mais si la configuration par l'intermédiaire de l' attributes hash / méthode (comme dans cet exemple), vous devez utiliser le nom de l'attribut, class.

  • Comme d'épine Dorsale 0.9.9:

    Lors de la déclaration d'un point de Vue...el, tagName, id et className peuvent maintenant être définies comme des fonctions, si vous voulez leurs valeurs lors de l'exécution.

    Je parle de cela dans le cas où il y a des situations où ce serait utile, comme une alternative à l'utilisation d'un attributes méthode, comme illustré.

À l'aide d'un élément existant

Si vous êtes à l'aide d'un élément existant (par exemple: passage de el pour le constructeur de la vue)...

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

...puis, attributes ne sera pas appliqué à l'élément. Si les attributs ne sont pas déjà fixé sur l'élément, ou vous ne voulez pas de duplication de données dans votre point de vue de la classe et un autre emplacement, vous pouvez ajouter un initialize méthode de votre point de vue constructeur qui s'applique attributes de el. Quelque chose comme ceci (à l'aide d' jQuery.attr):

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

L'utilisation de el, de rendu, en évitant le wrapper

Dans la plupart des exemples que j'ai vu, le point de vue d'el sert un sens wrapper élément à l'intérieur de laquelle on a à écrire manuellement le 'sémantique' code.

Il n'y a pas de raison view.el doit être "un sens élément wrapper". En fait, ce serait se cassent souvent les DOM structure. Si une classe d'affichage représente un <li> élément par exemple, il doit être restitué comme un <li> -- rendu comme un <div> ou tout autre élément de casser le modèle de contenu. Vous aurez probablement envie de se concentrer sur configurer correctement votre point de vue de l'élément (en utilisant les propriétés comme l' tagName, className, et id) puis le rendu de son contenu par la suite.

Les options pour votre épine Dorsale de visualiser les objets d'interagir avec les DOM sont grandes ouvertes. Il y a 2 initial de base de scénarios:

  • Vous pouvez joindre une élément du DOM à l'épine Dorsale de la vue.

  • Vous pouvez autoriser l'épine Dorsale de créer un nouvel élément qui est déconnecté du document, puis d'une certaine manière de l'insérer dans le document.

Il existe plusieurs façons vous pouvez générer le contenu de l'élément (ensemble une chaîne littérale, comme dans votre exemple; utilisation d'une bibliothèque de templates comme la Moustache, Guidon, etc.). La façon dont vous devriez utiliser l' el de la propriété de la vue dépend de ce que vous êtes en train de faire.

Élément existant

Votre rendu exemple suggère que vous avez un élément que vous assignez à la vue, même si vous ne vous présentez pas à l'instanciation de la vue. Si c'est le cas, et l'élément est déjà dans le document, alors vous voudrez peut-être faire quelque chose comme ça (mettre à jour le contenu de el, mais ne pas altérer el lui-même):

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

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

Élément généré

Disons que vous ne disposez pas d'un élément et vous permettre d'épine Dorsale pour en générer un pour vous. Vous pouvez vouloir faire quelque chose comme cela (mais c'est probablement mieux de l'architecte de choses, de sorte que votre point de vue n'est pas responsable pour savoir à propos de quelque chose d'extérieur à lui-même):

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

http://jsfiddle.net/vQMa2/

Modèles

Dans mon cas, je suis à l'aide de modèles, par exemple:

<div class="player" id="{{id}}">
<input name="name" value="{{name}}" />
<input name="score" value="{{score}}" />
</div>
<!-- .player -->

Le modèle représente le point de vue complet. En d'autres termes, il n'y aura pas de wrapper autour du modèle -- div.player sera la racine ou ultrapériphériques de l'élément de mon point de vue.

Mon joueur de classe va ressembler à quelque chose comme ceci (avec très simplifiée, render()):

Backbone.View.extend( {
  tagName : 'div',
  className : 'player',

  attributes : function () {
    return {
      id : "player-" + this.model.cid
    };
  },
  // attributes

  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() );
  }      
} );

95voto

Dan Brooke Points 1314

À votre avis, faites 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'); 
   }       
});
 

27voto

Jørgen Points 3422

Vous pouvez définir les propriétés de l' 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 de réglage de l'id basé sur les paramètres du constructeur

Si les points de vue sont construits comme il est mentionné:

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

Ensuite, les valeurs pourraient être définie de cette manière:

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

6voto

Marcus Points 1762

Je sais que c'est une vieille question, mais il a ajouté de référence. Cela semble être plus facile dans la nouvelle colonne vertébrale versions. De la colonne vertébrale 1.1 l'id et le nom de la classe de propriétés sont évaluées dans la fonction ensureElement (voir à partir de la source) à l'aide de souligner _.result de sens que si className ou id est une fonction, il sera appelé, sinon sa valeur sera utilisée.

Si vous pouviez donner un nom de classe directement dans le constructeur, donner un autre paramètre qui sera utilisé dans le nom de la classe, 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'); }
});

4voto

diskodave Points 53

Les autres exemples ne montrent pas comment récupérer réellement les données du modèle. Pour ajouter dynamiquement id et class à 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'); 
   }       
});
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X