¿Cómo obtengo un solo modelo en Backbone?


93

Tengo un Clockmodelo en Backbone:

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

Estoy tratando de obtener una instancia de eso que tenga la información más reciente de /clocks/123. Algunas cosas que he probado:

un método de nivel de "clase"

Clock.fetch(123)
// TypeError: Object function (){ ... } has no method 'fetch'

creando una instancia y luego invocándola fetch:

c = new Clock({id: 123})
c.fetch()
// Error: A 'url' property or function must be specified

Una colección

Intenté crear un AllClocksrecurso de colección (aunque no tengo ningún uso para tal cosa en la página):

var AllClocks = Backbone.Collection.extend({
  model: Clock,
  url: '/clocks/'
});
var allClocks = new AllClocks();
allClocks.fetch(123);
// returns everything from /clocks/

¿Cómo obtengo un reloj respaldado por API?


En mi humilde opinión, pertenece a la colección. Algo como Collection # fetchOne (id, callback).
— Julian Maicher

Respuestas:


26

Su segundo enfoque es el enfoque que he utilizado. Intente agregar lo siguiente a su modelo de reloj:

url : function() {
  var base = 'clocks';
  if (this.isNew()) return base;
  return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + this.id;
},

Este enfoque asume que ha implementado controladores con el hashbang en su URL como ese, http://www.mydomain.com/#clocks/123 , pero debería funcionar incluso si aún no lo ha hecho.


3
Hay una forma de evitar esto, como se explica en la documentación del modelo Backbone documentcloud.github.com/backbone/#Model-url
— makevoid

@makevoid your No pude hacer que funcione el ejemplo que proporciona en el script de café o el de la documentación, el ejemplo de Andrew funciona, ¿podría proporcionar un ejemplo con foo.url (), siempre me dice que no hay una URL de función.
— Roberto Alarcón

@makevoid parece que el método al que se refiere solo funciona si el modelo se ha creado en una colección. Observe la colección en [collection.url]/[id].
— Steven Devijver

@makevoid, ¿puede proporcionar un enlace que funcione? desafortunadamente, este está roto por ahora
— AlexNikolaev94

aquí está el enlace de trabajo (¡movieron el documento! wow, pasaron 5 años, caramba): backbonejs.org/#Model-url - @StevenDevijver es correcto
— makevoid

137

Intente especificar urlRoot en el modelo:

De los documentos:

var Book = Backbone.Model.extend({urlRoot : '/books'});
var solaris = new Book({id: "1083-lem-solaris"});
solaris.fetch();

2
Esto es bueno, pero a veces no desea restablecer el modelo. Si desea buscar un elemento específico contra el mismo modelo, puede hacer una serie silenciosa: currentBook.set('id', 13423, {silent:true}). Esto también funciona, pero no estoy seguro de por qué:currentBook.id = 13423
— SimplGy

1
@SimplGy que funciona porque model.ides esencialmente sinónimo de model.attributes.id. Si llama model.set('id'), Backbone establece model.idlo que haya especificado. Y model.ides lo que se usa al crear la URL específica del modelo.
— Lambart

26

Personalmente recomiendo, siguiendo la documentación del método Model # url

model = new Model(id: 1)
view = new View(model: model) 
collection = new Collection([model])
model.fetch()

en su colección recuerde agregar la URL de la colección:

url: "/models"

y en la función de inicialización de su Vista haga:

this.model.bind("change", this.render)

de esta manera, la red troncal hará una solicitud ajax usando esta URL:

"/models/1"

su modelo será actualizado y la vista renderizada, sin modificar Collection # url o Model # urlRoot

nota: lo siento, este ejemplo salió en el script de café, pero puede traducirlo fácilmente a js agregando declaraciones var


Aparentemente esto no funciona. Ni siquiera haga una llamada al servidor cuando llame a buscar en el modelo (ni en la colección)
— Ricardo Amores

Esto se ve bien, pero la línea de colección parece incómoda en los casos en que realmente no necesitamos la colección.
— Dingle

No pude hacer que esto funcione: this.model.get ('campo'). Parece que el modelo es un subobjeto creado
— Muhaimin

1
this.model.bind ("change", this.render, this) funcionó bien para mí
— dmi3y

1
@UlysseBN sí (era el año 2011), puede agregar declaraciones var, {}dentro de las ()'s para los objetos pasados ​​y un ;anuncio opcional al final de las líneas
— makevoid

12
var Person = Backbone.Model.extend({urlRoot : '/person/details'});
var myName = new Person({id: "12345"});
myName.fetch();

Como resultado, realiza una solicitud Ajax en el

URL http://[domainName]/person/details/id 

y tienes la respuesta JSON de vuelta.

Enjoyiiii !!!


2
esta es la misma solución que @Hernan
— Brenden

0

... y haz esto si no quieres la barra diagonal en el modelo urlRoot:

    url : function() {                        
        return this.urlRoot + this.id;
    },

0

Probablemente debería acceder al objeto a través de una colección y mantenerlo en la colección todo el tiempo. Asi es como se hace:

var AllClocks = Backbone.Collection.extend({
  model: Clock,
  url: '/clocks/'
});

var allClocks = new AllClocks();
my_clock = allClocks.add({id: 123});
my_clock.fetch()

2
No lo sabes. Quizás todo lo que necesita es un reloj. Supongamos que quiero presentarle a un cliente un único modelo de registro de usuario. ¿También debería tener acceso a una colección de todos los usuarios? A veces, la gente solo necesita un consejo mientras intenta mantener en privado su caso de uso. Solo responde.
— Adrian Bartholomew

0

Quiero usar la URL RESTful, pero no puedo entender por qué no se puede agregar 'postId' a la URL base.

var PostModel = Backbone.Model.extend({
    urlRoot: 'getBlogPost',
    defaults: {
        postTitle: "defaultTitle",
        postTime: "1970-01-01",
        postContent: "defaultContent",
        postAuthor: "anonymous"
    }
});

var post = new PostModel({
            postId: 1
        });
alert(post.url());

Entonces sé que solo después de configurar 'idAttribute' como 'postId' en Model puedo obtener la URL correcta. Me gusta esto:

var PostModel = Backbone.Model.extend({
    idAttribute: 'postId',
    urlRoot: 'getBlogPost',
    defaults: {
        postTitle: "defaultTitle",
        postTime: "1970-01-01",
        postContent: "defaultContent",
        postAuthor: "anonymous"
    }
});
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.