Here is my widget module:
app.module("Widget.MyWidget", function(MyWidget, app, Backbone, Marionette, $, _) {
this.on("start", function(el){
var that = this;
});
this.on("click", function(el){
alert("click");
});
this.renderWidget = function (id) {
var that = this;
var el = '#widget_' + id;
widgetModel = new app.Widget.MyWidget.models.meteo();
widgetModel.getWidget(id)
.fetch({ type: "GET" })
.done(function(){
var widgetView = new that.views.widgetView({model:widgetModel, el : el});
widgetView.render();
})
});
};
});
and here is the Marionette view:
define(['hbs!modules/myWidget'],function (template) {
var meteoView = Marionette.ItemView.extend({
template: template,
events: {
"dblclick" : "open",
"click" : "select",
"contextmenu .icon.doc" : "showMenu",
"click .show_notes" : "toggleNotes",
"click .title .lock" : "editAccessLevel",
"mouseover" : "showTooltip"
},
onShow: function(){
var view = this;
alert("showing");
}
});
return meteoView;
});
Everything works perfectly: the model is loaded and populated with data, the view is rendered on screen with the data.
But, I cannot set any event on the view: I would like to attach a click event to the view: What do I do wrong ?
regards
You must define your callbacks in your view :
var meteoView = Marionette.ItemView.extend({
....
open: function() {},
select: function() {},
showMenu: function() {},
toggleNotes: function() {},
editAccessLevel: function() {},
showTooltip: function() {},
....
}
Related
There's a remove method on EventView. When I click on the remove button, the Event (Model) should be removed so as the EventView.
With the following code, I can remove the Model from mongodb by clicking on the remove button. But the Model View won't remove itself until I refresh the page.
I am using express, EJS and mongodb for this demo.
app.js // with express routes settings
events.init = function(req, res) { res.render('index') };
events.all = function(req, res) {
db.event.find({}, function(err, event) {
if (err) return;
res.json(event);
});
}
events.delete = function (req, res) {
var Id = db.ObjectId(req.params.id);
db.event.remove({
"_id": Id
});
}
app.get('/', events.init);
app.get('/events', events.all);
app.del('/events/:id', events.delete);
client.js // Backbone Model, Collection and View setup
var Event = Backbone.Model.extend({
idAttribute: "_id"
});
var EventCollection = Backbone.Collection.extend({
model: Event,
url: "/events"
});
var EventView = Backbone.View.extend({
events: {
"click .remove": "remove"
},
initialize: function () {
this.listenTo(this.model, 'destroy', this.remove);
},
remove: function (e) {
this.model.destroy();
},
render: function () {
var html = new EJS({url: '/partials/event-field.ejs'}).render(this.model);
this.$el.html(html);
return this
}
});
var EventCollectionView = Backbone.View.extend({
render: function () {
this.collection.each(function(event){
var eventView = new EventView({ model: event });
this.$el.append(eventView.render().$el);
}, this);
return this
}
});
init.js // Called on page load
$(function () {
var collection = new EventCollection();
collection.fetch({
success: function(data){
var collectionView = new EventCollectionView({ collection: data})
$('.upcoming .list-group').append(collectionView.render().$el);
}
});
});
Somehow I found out how to make it work.
I renamed the remove method to destroy and changed the destroy method like so.
events: {
"click .remove": "destroy"
},
initialize: function () {
this.listenTo(this.model, 'destroy', this.destroy);
},
destroy: function () {
this.remove();
this.unbind();
this.model.destroy();
},
Total newbie to Backbone so apologize if this is a simple question.
I am have successfully loaded a collection and rendered the view. However I have a dropdown with A tags that I would like to use the filter the data displayed. I'm trying to set an event listener in my VIEW and then trigger a function within the view to filter the results and re-render the view.
Here's my code:
IBA.NewsModel = Backbone.Model.extend({});
IBA.NewsCollection = Backbone.Collection.extend({
model: IBA.NewsModel,
url: "/news/api"
});
IBA.NewsView = Backbone.View.extend({
el: '#main',
template: _.template($("#news-article").html()),
events: {
"change .dropdown-item": "filterNews"
},
initialize: function () {
this.collection = new IBA.NewsCollection();
this.listenTo(this.collection, 'reset', this.render);
this.collection.fetch({
success: function() {
console.log("JSON file load was successful");
view.render();
},
error: function(){
console.log('There was some error in loading and processing the JSON file');
}
});
},
render: function () {
this.$el.html(this.template({
articles: this.collection.toJSON()
})
);
return this;
},
filterNews: function (e){
e.preventDefault();
var items = this.collection.where({cat_name: "interviews"});
console.log(items);
this.$el.html(this.template({articles: this.items.toJSON()}));
}
});
var view = new IBA.NewsView();
Easiest way to do it would be to reset the actual collection with the filtered results:
IBA.NewsModel = Backbone.Model.extend({});
IBA.NewsCollection = Backbone.Collection.extend({
model: IBA.NewsModel,
url: "/news/api"
});
IBA.NewsView = Backbone.View.extend({
el: '#main',
template: _.template($("#news-article").html()),
events: {
"change .dropdown-item": "filterNews"
},
initialize: function() {
this.collection = new IBA.NewsCollection();
this.listenTo(this.collection, 'reset', this.render);
this.fetchNews();
},
fetchNews: function() {
var view = this;
this.collection.fetch({
success: function() {
console.log("JSON file load was successful");
view.render();
},
error: function() {
console.log('There was some error in loading and processing the JSON file');
}
});
},
render: function() {
this.$el.html(this.template({
articles: this.collection.toJSON()
}));
return this;
},
filterNews: function(e) {
e.preventDefault();
this.collection.reset(this.collection.where({
cat_name: "interviews"
}));
}
});
var view = new IBA.NewsView();
When you want to go back to original data, fetch it again using the fetchNews() method.
You also had a syntax error that view was not defined in your initialize
I just started to learn BackboneJS and getting deeper inside I face a problem. I have a bootstrap modal where I would like populate the modal-content in function of a called event fired in my main view and try to figure out how to inject a subview in my Modal view which is dynamically generated. So far my code looks like but not working
Main view
//here events are mapped
Fefe.Views = Fefe.Views || {};
(function () {
'use strict';
Fefe.Views.Editor = Backbone.View.extend({
template: JST['app/scripts/templates/editor.ejs'],
tagName: 'div',
el: '.container',
id: '',
className: '',
events: {
"click button.expand" : "controlToggle",
"click .grid" : "grid"
},
controlToggle: function(e){
var controlls = $(e.currentTarget).closest('.editor-controls')
$(controlls).find('.active').removeClass('active')
$(e.currentTarget).parent().addClass('active')
},
grid: function() {
this.model = new Fefe.Models.Grids({
'title': 'Edit Grids'
})
var gridView = new Fefe.Views.Grids({
model: this.model
})
var grids = new Fefe.Views.Modal({
model : this.model,
subview: gridView
}).render()
},
initialize: function () {
var body = $('body')
var rows = body.find('.row')
$.each(rows, function(e , v){
$(this).addClass('editor-row empty-row')
})
$('.sortable-rows').sortable({ handle: 'button.row-handle.btn.btn-default' })
this.listenTo(this.model, 'change', this.render);
},
render: function () {
return this;
}
});
})();
Modal view
//this one holds the modal markup
Fefe.Views = Fefe.Views || {};
(function () {
'use strict';
Fefe.Views.Modal = Backbone.Marionette.View.extend({
template: JST['app/scripts/templates/modal.ejs'],
subview: '',
className: "modal",
attributes: {
tabindex: "-1",
role: "dialog",
},
initialize: function() {
this.template = this.template;
console.log(this)
},
events: {
"click .save": "save",
"click .close": "close",
"change input": "modify",
},
render: function(e) {
this.$el.html(this.template(this.model.toJSON())).modal()
$(".modal-dialog").draggable({
handle: ".modal-header"
})
return this
},
show: function() {
$(document.body).append(this.render().el);
},
close: function() {
this.remove();
},
save: function() {
if(this.model.id == null) {
tasks.create(this.model);
}
else {
this.model.save();
}
this.remove();
},
edit: function(e) {
var attribute = {};
attribute[e.currentTarget.name] = e.currentTarget.value;
this.model.set(attribute);
},
});
})();
Maybe the approach is wrong and I'm on the wrong track
You should checkout the way with custom regions, described by Brian Mann at backbonerails.com
So the idea is following:
1) Define a region in your app with special class, lets call it DialogRegion
regions: {
dialogs: {
selector: '#dialogs',
regionClass: DialogRegion
}
}
2) Extend DialogRegion like following. I used Bootstrap modal API, please expect
var DialogRegion = Marionette.Region.extend({
onShow: function(view) {
view.$el.addClass('modal');
view.$el.modal();
// add handler to close popup via event
view.on('before:destroy', function() {
view.$el.modal('hide');
});
//destroy view on popup close
view.$el.on('hidden.bs.modal', function (e) {
view.destroy();
});
})
})
3) Later from any place of your app you can render Modal via rendering any view in dialogs App region:
App.dialogs.show( new SomeSuperView({
model: model
}))
I recommend you to checkout tutorial at Backbonerails to clarify this way. Hope you will find it usefull
I'm learning Backbone with RequireJS and I have got a problem when trying to instantiate additional model in my view. I have couple of events which are calling different methods. Different methods are using more or less different models and subviews The example above drops on new model instance
TypeError: GridsModel is not a constructor
var gridModel = new GridsModel;
when fireing grid method
My code looks like
/*global define*/
define([
'jquery',
'underscore',
'backbone',
'templates',
'jqueryui',
'models/grids',
'views/grids',
'views/modal'
], function ($, _, Backbone, JST, GridsModel, GridsView, ModalView) {
'use strict';
var EditorView = Backbone.View.extend({
template: JST['app/scripts/templates/editor.ejs'],
tagName: 'div',
el: '.container',
id: '',
className: '',
events: {
"click button.expand" : "controlToggle",
"click .row-edit" : "edit",
"click .grid" : "grid",
"click .delete" : "delete",
"click .components" : "components",
},
initialize: function () {
var gridModel = new GridsModel;
var body = $('body')
var rows = body.find('.row')
console.log(this.model)
$.each(rows, function(e , v){
if(v.length > 0)
console.log(v)
//$(this).parent().addClass('editor-row')
else
//console.log($(this))
$(this).addClass('editor-row empty-row')
})
$('.ui-sortable').sortable({ handle: 'button.row-handle' })
this.listenTo(this.model, 'change', this.render);
this.listenTo(this.model, 'change', this.render);
},
render: function () {
this.$el.html(this.template(this.model.toJSON()));
},
controlToggle: function(e){
var controlls = $(e.currentTarget).closest('.editor-controls')
$(controlls).find('.active').removeClass('active')
$(e.currentTarget).parent().addClass('active')
},
edit: function(){
},
delete: function() {
confirm('Press OK to delete section, Cancel to leave')
},
grid: function() {
this.model = new GridsModel({
'title': 'Edit Grids'
})
var gridView = new GridsView({
model: this.model
})
var grids = new ModalView({
model : this.model,
subview: gridView
}).render()
},
components: function() {
this.model = new Fefe.Models.Components({
'title': 'Add Component'
})
var componentsView = new Fefe.Views.Components({
model: this.model
})
var components= new Fefe.Views.Modal({
model : this.model,
className: 'modal large',
subview: componentsView
}).render()
}
});
return EditorView;
});
What do I do wrong here
I have this simple BackboneJS app and it keeps returning this error on adding new model to collection: Cannot call method 'on' of undefined. Can someone help me. I can't see the problem in here.I have my templates defined in index.html, and I am using Slim framework and NotORM.
(function(){
window.App =
{
Models:{},
Collections: {},
Views : {}
}
window.template = function(id)
{
return _.template( jQuery('#' + id).html());
}
App.Models.Party = Backbone.Model.extend({
});
App.Collections.Partys = Backbone.Collection.extend({
model: App.Models.Party,
url: "http://localhost/BackboneJS/vjezba6/server/index.php/task"
});
App.Views.Party = Backbone.View.extend({
tagName :"div",
className: "box shadow aktivan",
template: template("boxovi"),
initialize: function()
{
this.model.on('change', this.render, this);
},
events:{
"click .izbrisi" : "izbrisi"
},
render: function()
{
var template = this.template( this.model.toJSON() );
this.$el.html(template);
return this;
},
izbrisi: function()
{
this.model.destroy();
},
ukloni: function()
{
this.remove();
}
});
App.Views.Partys = Backbone.View.extend({
tagName:"div",
id: "nosac-boxova",
initialize: function()
{
},
render: function() {
this.collection.each(this.addOne, this);
return this;
},
addOne: function(party) {
var partyView = new App.Views.Party({ model: party });
this.$el.append(partyView.render().el);
}
});
App.Views.Dodaj = Backbone.View.extend({
tagName: "div",
template : template("dodajTemp"),
events:
{
'submit' : 'submit'
},
submit : function(e)
{
e.preventDefault();
console.log(e);
var nazivPolje = $(e.currentTarget).find(".naziv").val();
var tekstPolje = $(e.currentTarget).find(".lokal").val();
var noviParty = new App.Views.Party({naziv:nazivPolje, tekst: tekstPolje});
this.collection.create(noviParty);
},
initialize: function()
{
},
render: function()
{
var template = this.template();
this.$el.html(template);
return this;
}
});
/* var kolekcijaPartya = new App.Collections.Partys([
{
naziv:"Ovo je prvi naziv",
tekst: "Ovo je prvi tekst"
},
{
naziv:"Ovo je drugi naziv",
tekst: "Ovo je drugi tekst"
}
]);*/
var kolekcijaPartya = new App.Collections.Partys;
kolekcijaPartya.fetch({
success: function()
{
var partysView = new App.Views.Partys({collection:kolekcijaPartya});
$("#content").prepend(partysView.render().el);
$("div.box").slideAj();
var dodajView = new App.Views.Dodaj({collection: kolekcijaPartya});
$("div#sidebar-right").html(dodajView.render().el);
}
});
})();
var noviParty = new App.Views.Party({naziv:nazivPolje, tekst: tekstPolje});
this.collection.create(noviParty);
so you are trying to add a View to your collection?