Como faço para buscar um único modelo no Backbone?


93

Tenho um Clockmodelo no Backbone:

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

Estou tentando obter uma instância disso que contém as informações mais recentes /clocks/123. Algumas coisas que tentei:

um método de nível de "classe"

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

criar uma instância e, em seguida, chamá fetch-la:

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

uma coleção

Tentei criar um AllClocksrecurso de coleção (embora não tenha uso para tal coisa na página):

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

Como faço para obter apenas um relógio apoiado por API?


IMHO ele pertence à coleção. Algo como Collection # fetchOne (id, callback).
Julian Maicher

Respostas:


26

Sua segunda abordagem é a abordagem que usei. Experimente adicionar o seguinte ao seu modelo de Relógio:

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

Esta abordagem assume que você implementou controladores com o hashbang em sua URL, como, http://www.mydomain.com/#clocks/123 , mas deve funcionar mesmo se você ainda não o fez.


3
Há uma maneira de evitar isso, conforme explicado na documentação do modelo de backbone documentcloud.github.com/backbone/#Model-url
makevoid

@makevoid seu Eu não consegui fazer funcionar o exemplo que você forneceu no script de café ou aquele na documentação, o exemplo do Andrew funciona, você poderia fornecer um exemplo com foo.url (), ele sempre me diz que não há url de função.
Roberto Alarcón

@makevoid parece que o método ao qual você está se referindo só funciona se o modelo tiver sido criado em uma coleção. Observe a coleção em [collection.url]/[id].
Steven Devijver

@makevoid pode fornecer um link funcional? infelizmente, este está quebrado por enquanto
AlexNikolaev94

aqui está o link de trabalho (eles mudaram o documento! uau, 5 anos se passaram, nossa): backbonejs.org/#Model-url - @StevenDevijver está correto
makevoid

137

Tente especificar urlRoot no modelo:

Dos documentos:

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

2
Isso é bom, mas às vezes você não quer reinstanciar o modelo. Se você quiser buscar um item específico contra o mesmo modelo, você pode fazer um conjunto silenciosa: currentBook.set('id', 13423, {silent:true}). Isso também funciona, mas não sei por quê:currentBook.id = 13423
SimplGy

1
@SimplGy que funciona porque model.idé essencialmente sinônimo de model.attributes.id. Se você chamar model.set('id'), o Backbone será definido model.idpara o que você especificou. E model.idé o que é usado ao criar a URL específica do modelo.
Lambart

26

Eu pessoalmente recomendo, seguindo a documentação do método Model # url

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

em sua coleção, lembre-se de adicionar o url da coleção:

url: "/models"

e na função de inicialização do seu View faça:

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

desta forma, o backbone fará uma solicitação ajax usando este url:

"/models/1"

seu modelo será atualizado e a visualização renderizada, sem modificar Collection # url ou Model # urlRoot

observação: desculpe, este exemplo saiu em script de café, mas você pode facilmente traduzi-lo para js adicionando instruções var


Aparentemente, isso não funciona. Nem faz uma chamada para o servidor ao chamar fetch no modelo (nem na coleção)
Ricardo Amores

Parece bom, mas a linha de coleção parece estranha nos casos em que não precisamos realmente da coleção.
Dingle

Não consegui fazer isso funcionar: this.model.get ('field'). Parece que o modelo foi criado
subobjeto

1
this.model.bind ("alterar", this.render, this) funcionou bem para mim
dmi3y

1
@UlysseBN sim (foi no ano de 2011), você pode adicionar instruções var, {}dentro do ()'s para os objetos passados ​​e opcional e ;no final das linhas
makevoid

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

Como resultado, você faz uma solicitação Ajax no

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

e você tem a resposta JSON de volta.

Enjoiiii !!!


2
esta é a mesma solução que @Hernan
Brenden

0

... e faça isso se você não quiser a barra final no modelo urlRoot:

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

0

Você provavelmente deve acessar o objeto por meio de uma coleção e mantê-lo na coleção o tempo todo. É assim que se faz:

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

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

2
Você não sabe disso. Talvez ele só precise de um relógio. Suponha que eu queira apresentar a um cliente um único modelo de registro de usuário. Ele deve ter acesso a uma coleção de todos os usuários também? Às vezes, o folk só precisa de alguns conselhos enquanto tenta manter seu caso de uso privado. Apenas responda.
Adrian Bartholomew

0

Quero usar o url RESTful, mas não consigo entender por que 'postId' não pode ser adicionado ao 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());

Então eu sei que só depois de definir 'idAttribute' como 'postId' em Model, posso obter o url correto. como isso:

var PostModel = Backbone.Model.extend({
    idAttribute: 'postId',
    urlRoot: 'getBlogPost',
    defaults: {
        postTitle: "defaultTitle",
        postTime: "1970-01-01",
        postContent: "defaultContent",
        postAuthor: "anonymous"
    }
});
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.