¿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.