Ошибка метода моделирования при попытке навигации

#javascript #backbone.js

#javascript #backbone.js

Вопрос:

У меня есть несколько базовых моделей, отображаемых в представлении коллекции, а также у меня есть маршрут, который должен отображать представление этой модели. Итак, здесь появляются представления

resume.js

 // this renders a single model for a collection view
var ResumeView = Backbone.View.extend({
    model: new Resume(),
    initialize: function () {
        this.template = _.template($('#resume').html());
    },
    render: function () {
        this.$el.html(this.template(this.model.toJSON));
        return this;
    }
});
  

#resume template

 <section id="resume">
    <h1><%= profession %></h1>
    <!-- !!!!! The link for a router which should navigate to ShowResume view -->
    <a href="#resumes/<%= id %>">View Details</a>
</section>
  

Представление коллекции:

 var ResumeList = Backbone.View.extend({
    initialize: function (options) {
        this.collection = options.collection;
        this.collection.on('add', this.render, this);
        // Getting the data from JSON-server
        this.collection.fetch({
            success: function (res) {
                _.each(res.toJSON(), function (item) {
                    console.log("GET a model with "   item.id);
                });
            },
            error: function () {
                console.log("Failed to GET"); 
            }
        });
    },
    render: function () {
        var self = this;
        this.$el.html('');
        _.each(this.collection.toArray(), function (cv) {
            self.$el.append((new ResumeView({model: cv})).render().$el);
        });
        return this;
    }        
});
  

Приведенный выше код работает отлично и делает именно то, что мне нужно — массив моделей извлекается с моего локального JSON-сервера, и каждая модель отображается в представлении коллекции. Однако проблема возникает, когда я пытаюсь перейти по моей ссылке в шаблоне выше. А вот и маршрутизатор:

 var AppRouter = Backbone.Router.extend({
    routes: {
        '': home,
        'resumes/:id': 'showResume'
    },
    initialize: function (options) {
        // layout is set in main.js
        this.layout = options.layout
    },
    home: function () {
        this.layout.render(new ResumeList({collection: resumes}));
    },
    showResume: function (cv) {
        this.layout.render(new ShowResume({model: cv}));
    }
});
  

и, наконец ShowResume , представление:

 var ShowResume = Backbone.View.extend({
    initialize: function (options) {
        this.model = options.model;
        this.template = _.template($('#full-resume').html());
    },
    render: function () {
        this.$el.html(this.template(this.model.toJSON()));
    }
});
  

Я не предоставил шаблон для этого представления, потому что он довольно большой, но ошибка заключается в следующем: всякий раз, когда я пытаюсь перейти по ссылке, представление пытается выполнить рендеринг, но возвращает мне следующую ошибку: Uncaught TypeError: this.model.toJSON is not a function. я подозреваю, что мой showResume метод в router недействителен, но я не могу понять, какчтобы заставить его работать правильно.

Ответ №1:

Вы передаете строку id URL 'resumes/:id' -адреса в качестве модели представления.

Это должно решить проблему.

 showResume: function (id) {
   this.layout.render(new ShowResume({
       model: new Backbone.Model({ 
           id: id,
           profession: "teacher" // you can pass data like this 
       })
   }));
}
  

Но вы должны извлекать данные в контроллере и соответствующим образом реагировать на представление.

 var AppRouter = Backbone.Router.extend({
    routes: {
        '*otherwise': 'home', // notice the catch all
        'resumes/:id': 'showResume'
    },
    initialize: function(options) {
        // layout is set in main.js
        this.layout = options.layout
    },
    home: function() {
        this.layout.render(new ResumeList({ collection: resumes }));
    },
    showResume: function(id) {
        // lazily create the view and keep it
        if (!this.showResume) {
            this.showResume = new ShowResume({ model: new Backbone.Model() });
        }

        // use the view's model and fetch
        this.showResume.model.set('id', id).fetch({
            context: this,
            success: function(){
                this.layout.render(this.showResume);
            }
        })

    }
});
  

Кроме того, this.model = options.model; это не нужно, так как Backbone автоматически подбирает model , collection , el , id , className , tagName , attributes и events , расширяя представление с их помощью.

Комментарии:

1. Еще раз спасибо, Эмиль! странно, но теперь он возвращает мне ошибку profession is not defined , хотя шаблон почти такой же, как приведенный выше

2. @AlexNikolaev94 Я обновил ответ, чтобы указать способ, которым он мог бы работать, но это действительно просто, и вы бы предпочли проверить, например, онлайн, которые демонстрируют хорошие шаблоны для маршрутизации и просмотров.

3. спасибо, Эмиль! это сработало, но теперь оно возвращает ту же ошибку, что и та, о которой я упоминал в моем предыдущем вопросе: A "url" property or function must be specified . Я должен выяснить, как извлекать данные, полученные из коллекции

4. @AlexNikolaev94 Задайте вопрос о коллекции, модели и представлении и о том, где они используются.