2016-10-12 2 views
-2

У меня есть представление коллекции с двумя методами фильтра и метод рендеринга, который принимает параметр. Проблема, с которой я столкнулся, заключается в том, что при первом представлении представления он возвращает мне ошибку. Вот моя коллекция:Предоставление представления возвращает undefined

var ResumeCollection = Backbone.Collection.extend({ 
    url: 'http://localhost:3000', 
    filterActive: function() { 
     var active = this.where({interviewed: false}); 
     return new ResumeCollection(active); 
    }, 
    filterInterviewed: function() { 
     var interviewed = this.where({interviewed: true}); 
     return new ResumeCollection(interviewed); 
    } 
}); 

И мое мнение:

var ResumeList = Backbone.View.extend({ 
    events { // hash array of filter events }, 
    initialize: function() { 
     this.collection.fetch(); 
    }, 

    render: function (filtered) { 
     var self = this; 
     var data; 

     if (!filtered) { 
      data = this.collection.toArray(); 
     } else { 
      data = filtered.toArray(); 
     } 

     _.each(data, function (cv) { 
      self.$el.append((new ResumeView({model: cv})).render().$el); 
     }); 

     return this; 
    }, 

    showActive: function (ev) { 
     var filtered = this.collection.filterActive(); 
     this.render(filtered); 
    }, 

    showInterviewed: function (ev) { 
     var filtered = this.collection.filterInterviewed(); 
     this.render(filtered); 
    }, 

    showAll: function (ev) { 
     this.render(this.collection); 
    } 
}); 

Этот вид визуализируется в первый раз в маршрутизаторе, передавая коллекцию:

var AppRouter = Backbone.Router.extend({ 
    routes: { 
     '': 'home' 
    }, 

    initialize: function() { 
     this.layout = new LayoutView(); 
    } 

    home: function() { 
     this.layout.render(new ResumeList({ 
      collection: new ResumeCollection() 
     })); 
    } 
}); 

И это макет вид, в пределах которого отображаются все другие виды:

var LayoutView = Backbone.View.extend({ 
    el: $('#outlet'), 
    render: function (view) { 
     if (this.child && this.child !== view) { 
      this.child.undelegateEvents(); 
     } 

     this.child = view; 
     this.child.setElement(this.$el).render(); 
     return this; 
    } 
}); 

Когда я просто обновляю свою страницу, я получаю ошибку filtered.toArray is not a function и ничего не отображается соответственно. После проверки всего в отладчике я узнал, что когда представление получает визуализацию в первый раз, атрибут filtered получает пустую коллекцию, присваивает ей переменную data, которая становится пустым массивом и переходит в тело функции render, становясь undefined после этого. Тайны идут здесь: всякий раз, когда я нажимаю элементы, привязанные к моим событиям show*, они действуют точно так, как ожидалось, и отображают любые модели, где interviewed === false, или true или всю коллекцию. Это выглядит для меня волшебным, и у меня нет ни малейшего понятия, что я могу с этим сделать.

ДОБАВЛЕНО: GitHub repo with this project

+2

Можете ли вы присоединить последние несколько строк стека вызовов от отладчика? Также вы не включаете код, который показывает, как этот ResumeList будет отображаться первым. Ваша функция 'showAll' прошла' this.collection', где я предполагаю, что лучшим поведением было бы не передавать ничего и полагаться на логику внутри рендера, чтобы выбрать значение по умолчанию, которое является 'this.collection'. Последнее - «var data = (отфильтровано || this.коллекция) .toArray() '- немного меньше подробностей? – mikeapr4

+0

Это приводит к появлению большего количества вопросов, но не вызывает вызов 'render()' – mikeapr4

+0

@ mikeapr4 У меня есть представление «layout», которое делает других похожими на его дочерние представления. – AlexNikolaev94

ответ

0

После куска советов от моего наставника, я понял, что суть проблемы заключается в асинхронном происхождении fetch метода - как я прошел this.collection.fetch в моей функции инициализации, она выполняется после моего render метода, а не до него , поэтому мой метод render не имел ничего, что можно было бы визуализировать при первом просмотре представления. Итак, это исправление работает:

var ResumeList = Backbone.View.extend({ 
    initialize: function (options) { 
     this.collection = options.collection(); 
     // removed .fetch() method from here 
    }, 
    render: function (filtered) { 
     var self = this; 
     var data; 
     // and added it here: 
     this.collection.fetch({ 
      success: function (collection) { 
       if (!filtered) { 
        data = collection.toArray(); 
       } else { 
        data = filtered.toArray(); 
       } 
       self.$el.html(self.template(collection.toJSON())); 
       _.each(data, function (cv) { 
        self.$el.append((new ResumeView({model: cv})).render().$el); 
       }) 
      } 
     }); 
    } 
}); 

И это сработало отлично и точно так, как мне было нужно.

1

Ваш home функция на AppRouter есть опечатка. У вас есть дополнительная точка с запятой.

home: function() { 
    this.layout.render(new ResumeList({ 
     collection: new ResumeCollection(); 
    })); 
} 

Должно быть

home: function() { 
    this.layout.render(new ResumeList({ 
     collection: new ResumeCollection() 
    })); 
} 

мне нужно, чтобы удалить его, чтобы получить JSFiddle работу: https://jsfiddle.net/4gyne5ev/1/

Я бы рекомендовал добавить какой-то пылеобразования инструмент в вашей IDE или процесс сборки (http://eslint.org/)

+0

ну, это была опечатка в моем вопросе, я дважды проверил свой код и, казалось, без таких опечаток, но это не работает. Я могу предоставить ссылку на github, если это поможет – AlexNikolaev94

0

Необходимо добавить исходный URL-адрес в файл db.json, как этот

"" : [ 
    { 
     'somthing': 'somthing' 
    } 
] 
+1

, к сожалению, это не помогло :( – AlexNikolaev94

+0

Пожалуйста, можете ли вы просто запустить консоль журнала (self.collection) и сообщить мне ответ? –

+1

пустая коллекция – AlexNikolaev94